diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-03 00:29:37 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-15 15:02:35 -0400 |
commit | a8fcffbde4cedf319f7009cec21baddf9422685e (patch) | |
tree | 844273a59ce2ab7b1a3ad0280eeaa73c4b64e9a0 /drivers | |
parent | 06bf27ddaae4deb796ec90a11c5ecefd7364e3ed (diff) |
Staging: meilhaus: remove the drivers
The comedi drivers should be used instead, no need to have
these in here as well.
Cc: David Kiliani <mail@davidkiliani.de>
Cc: Meilhaus Support <support@meilhaus.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
133 files changed, 0 insertions, 41014 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index d76f6b356de7..982e94456066 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -47,8 +47,6 @@ source "drivers/staging/slicoss/Kconfig" | |||
47 | 47 | ||
48 | source "drivers/staging/sxg/Kconfig" | 48 | source "drivers/staging/sxg/Kconfig" |
49 | 49 | ||
50 | source "drivers/staging/meilhaus/Kconfig" | ||
51 | |||
52 | source "drivers/staging/go7007/Kconfig" | 50 | source "drivers/staging/go7007/Kconfig" |
53 | 51 | ||
54 | source "drivers/staging/usbip/Kconfig" | 52 | source "drivers/staging/usbip/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 01bf2284520f..4eabb440a18e 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -6,7 +6,6 @@ obj-$(CONFIG_STAGING) += staging.o | |||
6 | obj-$(CONFIG_ET131X) += et131x/ | 6 | obj-$(CONFIG_ET131X) += et131x/ |
7 | obj-$(CONFIG_SLICOSS) += slicoss/ | 7 | obj-$(CONFIG_SLICOSS) += slicoss/ |
8 | obj-$(CONFIG_SXG) += sxg/ | 8 | obj-$(CONFIG_SXG) += sxg/ |
9 | obj-$(CONFIG_MEILHAUS) += meilhaus/ | ||
10 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ | 9 | obj-$(CONFIG_VIDEO_GO7007) += go7007/ |
11 | obj-$(CONFIG_USB_IP_COMMON) += usbip/ | 10 | obj-$(CONFIG_USB_IP_COMMON) += usbip/ |
12 | obj-$(CONFIG_W35UND) += winbond/ | 11 | obj-$(CONFIG_W35UND) += winbond/ |
diff --git a/drivers/staging/meilhaus/Kconfig b/drivers/staging/meilhaus/Kconfig deleted file mode 100644 index 923af22a4686..000000000000 --- a/drivers/staging/meilhaus/Kconfig +++ /dev/null | |||
@@ -1,128 +0,0 @@ | |||
1 | # | ||
2 | # Meilhaus configuration | ||
3 | # | ||
4 | |||
5 | menuconfig MEILHAUS | ||
6 | tristate "Meilhaus support" | ||
7 | depends on m | ||
8 | ---help--- | ||
9 | If you have a Meilhaus card, say Y (or M) here. | ||
10 | |||
11 | You need both this driver, and the driver for the particular | ||
12 | data collection card. | ||
13 | |||
14 | To compile this driver as a module, choose M here. The module will | ||
15 | be called memain. | ||
16 | |||
17 | if MEILHAUS | ||
18 | |||
19 | config ME0600 | ||
20 | tristate "Meilhaus ME-600 support" | ||
21 | default n | ||
22 | depends on PCI && m | ||
23 | help | ||
24 | This driver supports the Meilhaus ME-600 family of boards | ||
25 | that do data collection and multipurpose I/O. | ||
26 | |||
27 | To compile this driver as a module, choose M here: the module | ||
28 | will be called me0600. | ||
29 | |||
30 | config ME0900 | ||
31 | tristate "Meilhaus ME-900 support" | ||
32 | default n | ||
33 | depends on PCI && m | ||
34 | help | ||
35 | This driver supports the Meilhaus ME-900 family of boards | ||
36 | that do data collection and multipurpose I/O. | ||
37 | |||
38 | To compile this driver as a module, choose M here: the module | ||
39 | will be called me0900. | ||
40 | |||
41 | config ME1000 | ||
42 | tristate "Meilhaus ME-1000 support" | ||
43 | default n | ||
44 | depends on PCI && m | ||
45 | help | ||
46 | This driver supports the Meilhaus ME-1000 family of boards | ||
47 | that do data collection and multipurpose I/O. | ||
48 | |||
49 | To compile this driver as a module, choose M here: the module | ||
50 | will be called me1000. | ||
51 | |||
52 | config ME1400 | ||
53 | tristate "Meilhaus ME-1400 support" | ||
54 | default n | ||
55 | depends on PCI && m | ||
56 | help | ||
57 | This driver supports the Meilhaus ME-1400 family of boards | ||
58 | that do data collection and multipurpose I/O. | ||
59 | |||
60 | To compile this driver as a module, choose M here: the module | ||
61 | will be called me1400. | ||
62 | |||
63 | config ME1600 | ||
64 | tristate "Meilhaus ME-1600 support" | ||
65 | default n | ||
66 | depends on PCI && m | ||
67 | help | ||
68 | This driver supports the Meilhaus ME-1600 family of boards | ||
69 | that do data collection and multipurpose I/O. | ||
70 | |||
71 | To compile this driver as a module, choose M here: the module | ||
72 | will be called me1600. | ||
73 | |||
74 | config ME4600 | ||
75 | tristate "Meilhaus ME-4600 support" | ||
76 | default n | ||
77 | depends on PCI && m | ||
78 | help | ||
79 | This driver supports the Meilhaus ME-4600 family of boards | ||
80 | that do data collection and multipurpose I/O. | ||
81 | |||
82 | To compile this driver as a module, choose M here: the module | ||
83 | will be called me4600. | ||
84 | |||
85 | config ME6000 | ||
86 | tristate "Meilhaus ME-6000 support" | ||
87 | default n | ||
88 | depends on PCI && m | ||
89 | help | ||
90 | This driver supports the Meilhaus ME-6000 family of boards | ||
91 | that do data collection and multipurpose I/O. | ||
92 | |||
93 | To compile this driver as a module, choose M here: the module | ||
94 | will be called me6000. | ||
95 | |||
96 | config ME8100 | ||
97 | tristate "Meilhaus ME-8100 support" | ||
98 | default n | ||
99 | depends on PCI && m | ||
100 | help | ||
101 | This driver supports the Meilhaus ME-8100 family of boards | ||
102 | that do data collection and multipurpose I/O. | ||
103 | |||
104 | To compile this driver as a module, choose M here: the module | ||
105 | will be called me8100. | ||
106 | |||
107 | config ME8200 | ||
108 | tristate "Meilhaus ME-8200 support" | ||
109 | default n | ||
110 | depends on PCI && m | ||
111 | help | ||
112 | This driver supports the Meilhaus ME-8200 family of boards | ||
113 | that do data collection and multipurpose I/O. | ||
114 | |||
115 | To compile this driver as a module, choose M here: the module | ||
116 | will be called me8200. | ||
117 | |||
118 | config MEDUMMY | ||
119 | tristate "Meilhaus dummy driver" | ||
120 | default n | ||
121 | depends on PCI && m | ||
122 | help | ||
123 | This provides a dummy driver for the Meilhaus driver package | ||
124 | |||
125 | To compile this driver as a module, choose M here: the module | ||
126 | will be called medummy. | ||
127 | |||
128 | endif # MEILHAUS | ||
diff --git a/drivers/staging/meilhaus/Makefile b/drivers/staging/meilhaus/Makefile deleted file mode 100644 index 5ab2c1c9c861..000000000000 --- a/drivers/staging/meilhaus/Makefile +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for Meilhaus linux driver system | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_MEILHAUS) += memain.o | ||
6 | obj-$(CONFIG_ME1600) += me1600.o | ||
7 | obj-$(CONFIG_ME1000) += me1000.o | ||
8 | obj-$(CONFIG_ME1400) += me1400.o | ||
9 | obj-$(CONFIG_ME4600) += me4600.o | ||
10 | obj-$(CONFIG_ME6000) += me6000.o | ||
11 | obj-$(CONFIG_ME0600) += me0600.o | ||
12 | obj-$(CONFIG_ME8100) += me8100.o | ||
13 | obj-$(CONFIG_ME8200) += me8200.o | ||
14 | obj-$(CONFIG_ME0900) += me0900.o | ||
15 | obj-$(CONFIG_MEDUMMY) += medummy.o | ||
16 | |||
17 | |||
18 | me1600-objs := medevice.o medlist.o medlock.o me1600_device.o | ||
19 | me1600-objs += mesubdevice.o meslist.o meslock.o me1600_ao.o | ||
20 | |||
21 | me1000-objs := medevice.o medlist.o medlock.o me1000_device.o | ||
22 | me1000-objs += mesubdevice.o meslist.o meslock.o me1000_dio.o | ||
23 | |||
24 | me1400-objs := medevice.o medlist.o medlock.o me1400_device.o | ||
25 | me1400-objs += mesubdevice.o meslist.o meslock.o me8254.o me8255.o me1400_ext_irq.o | ||
26 | |||
27 | me4600-objs := medevice.o medlist.o medlock.o mefirmware.o me4600_device.o | ||
28 | 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 | ||
29 | |||
30 | me6000-objs := medevice.o medlist.o medlock.o mefirmware.o me6000_device.o | ||
31 | me6000-objs += mesubdevice.o meslist.o meslock.o me6000_dio.o me6000_ao.o | ||
32 | |||
33 | me0600-objs := medevice.o medlist.o medlock.o me0600_device.o | ||
34 | me0600-objs += mesubdevice.o meslist.o meslock.o me0600_relay.o me0600_ttli.o me0600_optoi.o me0600_dio.o me0600_ext_irq.o | ||
35 | |||
36 | me8100-objs := medevice.o medlist.o medlock.o me8100_device.o | ||
37 | me8100-objs += mesubdevice.o meslist.o meslock.o me8100_di.o me8100_do.o me8254.o | ||
38 | |||
39 | me8200-objs := medevice.o medlist.o medlock.o me8200_device.o | ||
40 | me8200-objs += mesubdevice.o meslist.o meslock.o me8200_di.o me8200_do.o me8200_dio.o | ||
41 | |||
42 | me0900-objs := medevice.o medlist.o medlock.o me0900_device.o | ||
43 | me0900-objs += mesubdevice.o meslist.o meslock.o me0900_do.o me0900_di.o | ||
diff --git a/drivers/staging/meilhaus/TODO b/drivers/staging/meilhaus/TODO deleted file mode 100644 index d6ce39823de6..000000000000 --- a/drivers/staging/meilhaus/TODO +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | TODO: | ||
2 | - checkpatch.pl cleanups | ||
3 | - sparse issues | ||
4 | - Lindent | ||
5 | - audit userspace interface | ||
6 | - handle firmware properly | ||
7 | - possible comedi merge | ||
8 | |||
9 | Please send cleanup patches to Greg Kroah-Hartman <greg@kroah.com> | ||
10 | and CC: David Kiliani <mail@davidkiliani.de> and Meilhaus Support <support@meilhaus.de> | ||
diff --git a/drivers/staging/meilhaus/me0600_device.c b/drivers/staging/meilhaus/me0600_device.c deleted file mode 100644 index bae17d264168..000000000000 --- a/drivers/staging/meilhaus/me0600_device.c +++ /dev/null | |||
@@ -1,213 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_device.c | ||
3 | * | ||
4 | * @brief ME-630 device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include "meids.h" | ||
42 | #include "meerror.h" | ||
43 | #include "mecommon.h" | ||
44 | #include "meinternal.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "medevice.h" | ||
48 | #include "me0600_device.h" | ||
49 | #include "mesubdevice.h" | ||
50 | #include "me0600_relay.h" | ||
51 | #include "me0600_ttli.h" | ||
52 | #include "me0600_optoi.h" | ||
53 | #include "me0600_dio.h" | ||
54 | #include "me0600_ext_irq.h" | ||
55 | |||
56 | me_device_t *me0600_pci_constructor(struct pci_dev *pci_device) | ||
57 | { | ||
58 | me0600_device_t *me0600_device; | ||
59 | me_subdevice_t *subdevice; | ||
60 | unsigned int version_idx; | ||
61 | int err; | ||
62 | int i; | ||
63 | |||
64 | PDEBUG("executed.\n"); | ||
65 | |||
66 | // Allocate structure for device instance. | ||
67 | me0600_device = kmalloc(sizeof(me0600_device_t), GFP_KERNEL); | ||
68 | |||
69 | if (!me0600_device) { | ||
70 | PERROR("Cannot get memory for device instance.\n"); | ||
71 | return NULL; | ||
72 | } | ||
73 | |||
74 | memset(me0600_device, 0, sizeof(me0600_device_t)); | ||
75 | |||
76 | // Initialize base class structure. | ||
77 | err = me_device_pci_init((me_device_t *) me0600_device, pci_device); | ||
78 | |||
79 | if (err) { | ||
80 | kfree(me0600_device); | ||
81 | PERROR("Cannot initialize device base class.\n"); | ||
82 | return NULL; | ||
83 | } | ||
84 | |||
85 | /* Get the index in the device version information table. */ | ||
86 | version_idx = | ||
87 | me0600_versions_get_device_index(me0600_device->base.info.pci. | ||
88 | device_id); | ||
89 | |||
90 | // Initialize spin lock . | ||
91 | spin_lock_init(&me0600_device->dio_ctrl_reg_lock); | ||
92 | spin_lock_init(&me0600_device->intcsr_lock); | ||
93 | |||
94 | // Create subdevice instances. | ||
95 | |||
96 | for (i = 0; i < me0600_versions[version_idx].optoi_subdevices; i++) { | ||
97 | subdevice = | ||
98 | (me_subdevice_t *) me0600_optoi_constructor(me0600_device-> | ||
99 | base.info.pci. | ||
100 | reg_bases[2]); | ||
101 | |||
102 | if (!subdevice) { | ||
103 | me_device_deinit((me_device_t *) me0600_device); | ||
104 | kfree(me0600_device); | ||
105 | PERROR("Cannot get memory for subdevice.\n"); | ||
106 | return NULL; | ||
107 | } | ||
108 | |||
109 | me_slist_add_subdevice_tail(&me0600_device->base.slist, | ||
110 | subdevice); | ||
111 | } | ||
112 | |||
113 | for (i = 0; i < me0600_versions[version_idx].relay_subdevices; i++) { | ||
114 | subdevice = | ||
115 | (me_subdevice_t *) me0600_relay_constructor(me0600_device-> | ||
116 | base.info.pci. | ||
117 | reg_bases[2]); | ||
118 | |||
119 | if (!subdevice) { | ||
120 | me_device_deinit((me_device_t *) me0600_device); | ||
121 | kfree(me0600_device); | ||
122 | PERROR("Cannot get memory for subdevice.\n"); | ||
123 | return NULL; | ||
124 | } | ||
125 | |||
126 | me_slist_add_subdevice_tail(&me0600_device->base.slist, | ||
127 | subdevice); | ||
128 | } | ||
129 | |||
130 | for (i = 0; i < me0600_versions[version_idx].ttli_subdevices; i++) { | ||
131 | subdevice = | ||
132 | (me_subdevice_t *) me0600_ttli_constructor(me0600_device-> | ||
133 | base.info.pci. | ||
134 | reg_bases[2]); | ||
135 | |||
136 | if (!subdevice) { | ||
137 | me_device_deinit((me_device_t *) me0600_device); | ||
138 | kfree(me0600_device); | ||
139 | PERROR("Cannot get memory for subdevice.\n"); | ||
140 | return NULL; | ||
141 | } | ||
142 | |||
143 | me_slist_add_subdevice_tail(&me0600_device->base.slist, | ||
144 | subdevice); | ||
145 | } | ||
146 | |||
147 | for (i = 0; i < me0600_versions[version_idx].dio_subdevices; i++) { | ||
148 | subdevice = | ||
149 | (me_subdevice_t *) me0600_dio_constructor(me0600_device-> | ||
150 | base.info.pci. | ||
151 | reg_bases[2], i, | ||
152 | &me0600_device-> | ||
153 | dio_ctrl_reg_lock); | ||
154 | |||
155 | if (!subdevice) { | ||
156 | me_device_deinit((me_device_t *) me0600_device); | ||
157 | kfree(me0600_device); | ||
158 | PERROR("Cannot get memory for subdevice.\n"); | ||
159 | return NULL; | ||
160 | } | ||
161 | |||
162 | me_slist_add_subdevice_tail(&me0600_device->base.slist, | ||
163 | subdevice); | ||
164 | } | ||
165 | |||
166 | for (i = 0; i < me0600_versions[version_idx].ext_irq_subdevices; i++) { | ||
167 | subdevice = | ||
168 | (me_subdevice_t *) | ||
169 | me0600_ext_irq_constructor(me0600_device->base.info.pci. | ||
170 | reg_bases[1], | ||
171 | me0600_device->base.info.pci. | ||
172 | reg_bases[2], | ||
173 | &me0600_device->intcsr_lock, i, | ||
174 | me0600_device->base.irq); | ||
175 | |||
176 | if (!subdevice) { | ||
177 | me_device_deinit((me_device_t *) me0600_device); | ||
178 | kfree(me0600_device); | ||
179 | PERROR("Cannot get memory for subdevice.\n"); | ||
180 | return NULL; | ||
181 | } | ||
182 | |||
183 | me_slist_add_subdevice_tail(&me0600_device->base.slist, | ||
184 | subdevice); | ||
185 | } | ||
186 | |||
187 | return (me_device_t *) me0600_device; | ||
188 | } | ||
189 | EXPORT_SYMBOL(me0600_pci_constructor); | ||
190 | |||
191 | // Init and exit of module. | ||
192 | |||
193 | static int __init me0600_init(void) | ||
194 | { | ||
195 | PDEBUG("executed.\n"); | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static void __exit me0600_exit(void) | ||
200 | { | ||
201 | PDEBUG("executed.\n"); | ||
202 | } | ||
203 | |||
204 | module_init(me0600_init); | ||
205 | |||
206 | module_exit(me0600_exit); | ||
207 | |||
208 | // Administrative stuff for modinfo. | ||
209 | MODULE_AUTHOR | ||
210 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
211 | MODULE_DESCRIPTION("Device Driver Module for ME-6xx Device"); | ||
212 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-6xx Devices"); | ||
213 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me0600_device.h b/drivers/staging/meilhaus/me0600_device.h deleted file mode 100644 index 75bd3b7351d2..000000000000 --- a/drivers/staging/meilhaus/me0600_device.h +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_device.h | ||
3 | * | ||
4 | * @brief ME-630 device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_DEVICE_H | ||
28 | #define _ME0600_DEVICE_H | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | /** | ||
38 | * @brief Structure holding ME-630 device capabilities. | ||
39 | */ | ||
40 | typedef struct me0600_version { | ||
41 | uint16_t device_id; | ||
42 | unsigned int relay_subdevices; | ||
43 | unsigned int ttli_subdevices; | ||
44 | unsigned int optoi_subdevices; | ||
45 | unsigned int dio_subdevices; | ||
46 | unsigned int ext_irq_subdevices; | ||
47 | } me0600_version_t; | ||
48 | |||
49 | /** | ||
50 | * @brief Device capabilities. | ||
51 | */ | ||
52 | static me0600_version_t me0600_versions[] = { | ||
53 | {PCI_DEVICE_ID_MEILHAUS_ME0630, 1, 1, 1, 2, 2}, | ||
54 | {0}, | ||
55 | }; | ||
56 | |||
57 | #define ME0600_DEVICE_VERSIONS (ARRAY_SIZE(me0600_versions) - 1) /**< Returns the number of entries in #me0600_versions. */ | ||
58 | |||
59 | /** | ||
60 | * @brief Returns the index of the device entry in #me0600_versions. | ||
61 | * | ||
62 | * @param device_id The PCI device id of the device to query. | ||
63 | * @return The index of the device in #me0600_versions. | ||
64 | */ | ||
65 | static inline unsigned int me0600_versions_get_device_index(uint16_t device_id) | ||
66 | { | ||
67 | unsigned int i; | ||
68 | for (i = 0; i < ME0600_DEVICE_VERSIONS; i++) | ||
69 | if (me0600_versions[i].device_id == device_id) | ||
70 | break; | ||
71 | return i; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * @brief The ME-630 device class structure. | ||
76 | */ | ||
77 | typedef struct me0600_device { | ||
78 | me_device_t base; /**< The Meilhaus device base class. */ | ||
79 | |||
80 | /* Child class attributes. */ | ||
81 | spinlock_t dio_ctrl_reg_lock; | ||
82 | spinlock_t intcsr_lock; | ||
83 | } me0600_device_t; | ||
84 | |||
85 | /** | ||
86 | * @brief The ME-630 device class constructor. | ||
87 | * | ||
88 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
89 | * | ||
90 | * @return On succes a new ME-630 device instance. \n | ||
91 | * NULL on error. | ||
92 | */ | ||
93 | me_device_t *me0600_pci_constructor(struct pci_dev *pci_device) | ||
94 | __attribute__ ((weak)); | ||
95 | |||
96 | #endif | ||
97 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_dio.c b/drivers/staging/meilhaus/me0600_dio.c deleted file mode 100644 index d29303518bed..000000000000 --- a/drivers/staging/meilhaus/me0600_dio.c +++ /dev/null | |||
@@ -1,415 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_dio.c | ||
3 | * | ||
4 | * @brief ME-630 digital input/output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me0600_dio_reg.h" | ||
48 | #include "me0600_dio.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me0600_dio_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | me0600_dio_subdevice_t *instance; | ||
62 | uint8_t mode; | ||
63 | |||
64 | PDEBUG("executed.\n"); | ||
65 | |||
66 | instance = (me0600_dio_subdevice_t *) subdevice; | ||
67 | |||
68 | if (flags) { | ||
69 | PERROR("Invalid flag specified.\n"); | ||
70 | return ME_ERRNO_INVALID_FLAGS; | ||
71 | } | ||
72 | |||
73 | ME_SUBDEVICE_ENTER; | ||
74 | |||
75 | spin_lock(&instance->subdevice_lock); | ||
76 | spin_lock(instance->ctrl_reg_lock); | ||
77 | mode = inb(instance->ctrl_reg); | ||
78 | mode &= ~(0x3 << (instance->dio_idx * 2)); | ||
79 | outb(mode, instance->ctrl_reg); | ||
80 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
81 | instance->ctrl_reg - instance->reg_base, mode); | ||
82 | spin_unlock(instance->ctrl_reg_lock); | ||
83 | |||
84 | outb(0x00, instance->port_reg); | ||
85 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
86 | instance->port_reg - instance->reg_base, 0x00); | ||
87 | spin_unlock(&instance->subdevice_lock); | ||
88 | |||
89 | ME_SUBDEVICE_EXIT; | ||
90 | |||
91 | return ME_ERRNO_SUCCESS; | ||
92 | } | ||
93 | |||
94 | static int me0600_dio_io_single_config(me_subdevice_t *subdevice, | ||
95 | struct file *filep, | ||
96 | int channel, | ||
97 | int single_config, | ||
98 | int ref, | ||
99 | int trig_chan, | ||
100 | int trig_type, int trig_edge, int flags) | ||
101 | { | ||
102 | me0600_dio_subdevice_t *instance; | ||
103 | int err = ME_ERRNO_SUCCESS; | ||
104 | uint8_t mode; | ||
105 | int size = | ||
106 | flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE | ||
107 | | ME_IO_SINGLE_CONFIG_DIO_WORD | | ||
108 | ME_IO_SINGLE_CONFIG_DIO_DWORD); | ||
109 | |||
110 | PDEBUG("executed.\n"); | ||
111 | |||
112 | instance = (me0600_dio_subdevice_t *) subdevice; | ||
113 | |||
114 | ME_SUBDEVICE_ENTER; | ||
115 | |||
116 | spin_lock(&instance->subdevice_lock); | ||
117 | spin_lock(instance->ctrl_reg_lock); | ||
118 | mode = inb(instance->ctrl_reg); | ||
119 | switch (size) { | ||
120 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
121 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
122 | if (channel == 0) { | ||
123 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
124 | mode &= | ||
125 | ~((ME0600_DIO_CONFIG_BIT_OUT_0) << | ||
126 | (instance->dio_idx * 2)); | ||
127 | } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
128 | mode &= | ||
129 | ~((ME0600_DIO_CONFIG_BIT_OUT_0) << | ||
130 | (instance->dio_idx * 2)); | ||
131 | mode |= | ||
132 | ME0600_DIO_CONFIG_BIT_OUT_0 << (instance-> | ||
133 | dio_idx * | ||
134 | 2); | ||
135 | } else { | ||
136 | PERROR | ||
137 | ("Invalid port configuration specified.\n"); | ||
138 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
139 | } | ||
140 | } else { | ||
141 | PERROR("Invalid channel number.\n"); | ||
142 | err = ME_ERRNO_INVALID_CHANNEL; | ||
143 | } | ||
144 | break; | ||
145 | |||
146 | default: | ||
147 | PERROR("Invalid flags.\n"); | ||
148 | err = ME_ERRNO_INVALID_FLAGS; | ||
149 | } | ||
150 | |||
151 | if (!err) { | ||
152 | outb(mode, instance->ctrl_reg); | ||
153 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
154 | instance->reg_base, | ||
155 | instance->ctrl_reg - instance->reg_base, mode); | ||
156 | } | ||
157 | spin_unlock(instance->ctrl_reg_lock); | ||
158 | spin_unlock(&instance->subdevice_lock); | ||
159 | |||
160 | ME_SUBDEVICE_EXIT; | ||
161 | |||
162 | return err; | ||
163 | } | ||
164 | |||
165 | static int me0600_dio_io_single_read(me_subdevice_t *subdevice, | ||
166 | struct file *filep, | ||
167 | int channel, | ||
168 | int *value, int time_out, int flags) | ||
169 | { | ||
170 | me0600_dio_subdevice_t *instance; | ||
171 | int err = ME_ERRNO_SUCCESS; | ||
172 | uint8_t mode; | ||
173 | |||
174 | PDEBUG("executed.\n"); | ||
175 | |||
176 | instance = (me0600_dio_subdevice_t *) subdevice; | ||
177 | |||
178 | ME_SUBDEVICE_ENTER; | ||
179 | |||
180 | spin_lock(&instance->subdevice_lock); | ||
181 | spin_lock(instance->ctrl_reg_lock); | ||
182 | switch (flags) { | ||
183 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
184 | if ((channel >= 0) && (channel < 8)) { | ||
185 | mode = | ||
186 | inb(instance-> | ||
187 | ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << | ||
188 | (instance->dio_idx * 2)); | ||
189 | |||
190 | if ((mode == | ||
191 | (ME0600_DIO_CONFIG_BIT_OUT_0 << | ||
192 | (instance->dio_idx * 2))) || !mode) { | ||
193 | *value = | ||
194 | inb(instance-> | ||
195 | port_reg) & (0x0001 << channel); | ||
196 | } else { | ||
197 | PERROR("Port not in output or input mode.\n"); | ||
198 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
199 | } | ||
200 | } else { | ||
201 | PERROR("Invalid bit number specified.\n"); | ||
202 | err = ME_ERRNO_INVALID_CHANNEL; | ||
203 | } | ||
204 | |||
205 | break; | ||
206 | |||
207 | case ME_IO_SINGLE_NO_FLAGS: | ||
208 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
209 | if (channel == 0) { | ||
210 | mode = | ||
211 | inb(instance-> | ||
212 | ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << | ||
213 | (instance->dio_idx * 2)); | ||
214 | |||
215 | if ((mode == | ||
216 | (ME0600_DIO_CONFIG_BIT_OUT_0 << | ||
217 | (instance->dio_idx * 2))) || !mode) { | ||
218 | *value = inb(instance->port_reg) & 0x00FF; | ||
219 | } else { | ||
220 | PERROR("Port not in output or input mode.\n"); | ||
221 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
222 | } | ||
223 | } else { | ||
224 | PERROR("Invalid byte number specified.\n"); | ||
225 | err = ME_ERRNO_INVALID_CHANNEL; | ||
226 | } | ||
227 | |||
228 | break; | ||
229 | |||
230 | default: | ||
231 | PERROR("Invalid flags specified.\n"); | ||
232 | |||
233 | err = ME_ERRNO_INVALID_FLAGS; | ||
234 | |||
235 | break; | ||
236 | } | ||
237 | spin_unlock(instance->ctrl_reg_lock); | ||
238 | spin_unlock(&instance->subdevice_lock); | ||
239 | |||
240 | ME_SUBDEVICE_EXIT; | ||
241 | |||
242 | return err; | ||
243 | } | ||
244 | |||
245 | static int me0600_dio_io_single_write(me_subdevice_t *subdevice, | ||
246 | struct file *filep, | ||
247 | int channel, | ||
248 | int value, int time_out, int flags) | ||
249 | { | ||
250 | me0600_dio_subdevice_t *instance; | ||
251 | int err = ME_ERRNO_SUCCESS; | ||
252 | uint8_t mode; | ||
253 | uint8_t byte; | ||
254 | |||
255 | PDEBUG("executed.\n"); | ||
256 | |||
257 | instance = (me0600_dio_subdevice_t *) subdevice; | ||
258 | |||
259 | ME_SUBDEVICE_ENTER; | ||
260 | |||
261 | spin_lock(&instance->subdevice_lock); | ||
262 | spin_lock(instance->ctrl_reg_lock); | ||
263 | switch (flags) { | ||
264 | |||
265 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
266 | if ((channel >= 0) && (channel < 8)) { | ||
267 | mode = | ||
268 | inb(instance-> | ||
269 | ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << | ||
270 | (instance->dio_idx * 2)); | ||
271 | |||
272 | if (mode == | ||
273 | (ME0600_DIO_CONFIG_BIT_OUT_0 << | ||
274 | (instance->dio_idx * 2))) { | ||
275 | byte = inb(instance->port_reg); | ||
276 | |||
277 | if (value) | ||
278 | byte |= 0x1 << channel; | ||
279 | else | ||
280 | byte &= ~(0x1 << channel); | ||
281 | |||
282 | outb(byte, instance->port_reg); | ||
283 | } else { | ||
284 | PERROR("Port not in output or input mode.\n"); | ||
285 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
286 | } | ||
287 | } else { | ||
288 | PERROR("Invalid bit number specified.\n"); | ||
289 | err = ME_ERRNO_INVALID_CHANNEL; | ||
290 | } | ||
291 | |||
292 | break; | ||
293 | |||
294 | case ME_IO_SINGLE_NO_FLAGS: | ||
295 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
296 | if (channel == 0) { | ||
297 | mode = | ||
298 | inb(instance-> | ||
299 | ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << | ||
300 | (instance->dio_idx * 2)); | ||
301 | |||
302 | if (mode == | ||
303 | (ME0600_DIO_CONFIG_BIT_OUT_0 << | ||
304 | (instance->dio_idx * 2))) { | ||
305 | outb(value, instance->port_reg); | ||
306 | } else { | ||
307 | PERROR("Port not in output or input mode.\n"); | ||
308 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
309 | } | ||
310 | } else { | ||
311 | PERROR("Invalid byte number specified.\n"); | ||
312 | err = ME_ERRNO_INVALID_CHANNEL; | ||
313 | } | ||
314 | |||
315 | break; | ||
316 | |||
317 | default: | ||
318 | PERROR("Invalid flags specified.\n"); | ||
319 | |||
320 | err = ME_ERRNO_INVALID_FLAGS; | ||
321 | |||
322 | break; | ||
323 | } | ||
324 | spin_unlock(instance->ctrl_reg_lock); | ||
325 | spin_unlock(&instance->subdevice_lock); | ||
326 | |||
327 | ME_SUBDEVICE_EXIT; | ||
328 | |||
329 | return err; | ||
330 | } | ||
331 | |||
332 | static int me0600_dio_query_number_channels(me_subdevice_t *subdevice, | ||
333 | int *number) | ||
334 | { | ||
335 | PDEBUG("executed.\n"); | ||
336 | *number = 8; | ||
337 | return ME_ERRNO_SUCCESS; | ||
338 | } | ||
339 | |||
340 | static int me0600_dio_query_subdevice_type(me_subdevice_t *subdevice, | ||
341 | int *type, int *subtype) | ||
342 | { | ||
343 | PDEBUG("executed.\n"); | ||
344 | *type = ME_TYPE_DIO; | ||
345 | *subtype = ME_SUBTYPE_SINGLE; | ||
346 | return ME_ERRNO_SUCCESS; | ||
347 | } | ||
348 | |||
349 | static int me0600_dio_query_subdevice_caps(me_subdevice_t *subdevice, | ||
350 | int *caps) | ||
351 | { | ||
352 | PDEBUG("executed.\n"); | ||
353 | *caps = ME_CAPS_DIO_DIR_BYTE; | ||
354 | return ME_ERRNO_SUCCESS; | ||
355 | } | ||
356 | |||
357 | me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base, | ||
358 | unsigned int dio_idx, | ||
359 | spinlock_t *ctrl_reg_lock) | ||
360 | { | ||
361 | me0600_dio_subdevice_t *subdevice; | ||
362 | int err; | ||
363 | |||
364 | PDEBUG("executed.\n"); | ||
365 | |||
366 | /* Allocate memory for subdevice instance */ | ||
367 | subdevice = kmalloc(sizeof(me0600_dio_subdevice_t), GFP_KERNEL); | ||
368 | |||
369 | if (!subdevice) { | ||
370 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
371 | return NULL; | ||
372 | } | ||
373 | |||
374 | memset(subdevice, 0, sizeof(me0600_dio_subdevice_t)); | ||
375 | |||
376 | /* Initialize subdevice base class */ | ||
377 | err = me_subdevice_init(&subdevice->base); | ||
378 | |||
379 | if (err) { | ||
380 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
381 | kfree(subdevice); | ||
382 | return NULL; | ||
383 | } | ||
384 | /* Initialize spin locks. */ | ||
385 | spin_lock_init(&subdevice->subdevice_lock); | ||
386 | |||
387 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
388 | |||
389 | /* Save digital i/o index */ | ||
390 | subdevice->dio_idx = dio_idx; | ||
391 | |||
392 | /* Save the subdevice index */ | ||
393 | subdevice->ctrl_reg = reg_base + ME0600_DIO_CONFIG_REG; | ||
394 | subdevice->port_reg = reg_base + ME0600_DIO_PORT_REG + dio_idx; | ||
395 | #ifdef MEDEBUG_DEBUG_REG | ||
396 | subdevice->reg_base = reg_base; | ||
397 | #endif | ||
398 | |||
399 | /* Overload base class methods. */ | ||
400 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
401 | me0600_dio_io_reset_subdevice; | ||
402 | subdevice->base.me_subdevice_io_single_config = | ||
403 | me0600_dio_io_single_config; | ||
404 | subdevice->base.me_subdevice_io_single_read = me0600_dio_io_single_read; | ||
405 | subdevice->base.me_subdevice_io_single_write = | ||
406 | me0600_dio_io_single_write; | ||
407 | subdevice->base.me_subdevice_query_number_channels = | ||
408 | me0600_dio_query_number_channels; | ||
409 | subdevice->base.me_subdevice_query_subdevice_type = | ||
410 | me0600_dio_query_subdevice_type; | ||
411 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
412 | me0600_dio_query_subdevice_caps; | ||
413 | |||
414 | return subdevice; | ||
415 | } | ||
diff --git a/drivers/staging/meilhaus/me0600_dio.h b/drivers/staging/meilhaus/me0600_dio.h deleted file mode 100644 index 5d075c7d6882..000000000000 --- a/drivers/staging/meilhaus/me0600_dio.h +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_dio.h | ||
3 | * | ||
4 | * @brief ME-630 digital input/output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_DIO_H_ | ||
28 | #define _ME0600_DIO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me0600_dio_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | unsigned int dio_idx; /**< The index of the digital i/o on the device. */ | ||
45 | |||
46 | unsigned long port_reg; /**< Register holding the port status. */ | ||
47 | unsigned long ctrl_reg; /**< Register to configure the port direction. */ | ||
48 | #ifdef MEDEBUG_DEBUG_REG | ||
49 | unsigned long reg_base; | ||
50 | #endif | ||
51 | } me0600_dio_subdevice_t; | ||
52 | |||
53 | /** | ||
54 | * @brief The constructor to generate a ME-630 digital input/ouput subdevice instance. | ||
55 | * | ||
56 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
57 | * @param dio_idx The index of the digital i/o port on the device. | ||
58 | * @param ctrl_reg_lock Spin lock protecting the control register. | ||
59 | * | ||
60 | * @return Pointer to new instance on success.\n | ||
61 | * NULL on error. | ||
62 | */ | ||
63 | me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base, | ||
64 | unsigned int dio_idx, | ||
65 | spinlock_t * ctrl_reg_lock); | ||
66 | |||
67 | #endif | ||
68 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_dio_reg.h b/drivers/staging/meilhaus/me0600_dio_reg.h deleted file mode 100644 index f116ea3b79d2..000000000000 --- a/drivers/staging/meilhaus/me0600_dio_reg.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_dio_reg.h | ||
3 | * | ||
4 | * @brief ME-630 digital input/output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_DIO_REG_H_ | ||
28 | #define _ME0600_DIO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME0600_DIO_CONFIG_REG 0x0007 | ||
33 | #define ME0600_DIO_PORT_0_REG 0x0008 | ||
34 | #define ME0600_DIO_PORT_1_REG 0x0009 | ||
35 | #define ME0600_DIO_PORT_REG ME0600_DIO_PORT_0_REG | ||
36 | |||
37 | #define ME0600_DIO_CONFIG_BIT_OUT_0 0x0001 | ||
38 | #define ME0600_DIO_CONFIG_BIT_OUT_1 0x0004 | ||
39 | |||
40 | #endif | ||
41 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_ext_irq.c b/drivers/staging/meilhaus/me0600_ext_irq.c deleted file mode 100644 index 1d098420a548..000000000000 --- a/drivers/staging/meilhaus/me0600_ext_irq.c +++ /dev/null | |||
@@ -1,469 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_ext_irq.c | ||
3 | * | ||
4 | * @brief ME-630 external interrupt subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | |||
43 | #include "medefines.h" | ||
44 | #include "meinternal.h" | ||
45 | #include "meerror.h" | ||
46 | #include "meids.h" | ||
47 | #include "medebug.h" | ||
48 | |||
49 | #include "meplx_reg.h" | ||
50 | #include "me0600_ext_irq_reg.h" | ||
51 | #include "me0600_ext_irq.h" | ||
52 | |||
53 | /* | ||
54 | * Functions | ||
55 | */ | ||
56 | |||
57 | static int me0600_ext_irq_io_irq_start(struct me_subdevice *subdevice, | ||
58 | struct file *filep, | ||
59 | int channel, | ||
60 | int irq_source, | ||
61 | int irq_edge, int irq_arg, int flags) | ||
62 | { | ||
63 | me0600_ext_irq_subdevice_t *instance; | ||
64 | uint32_t tmp; | ||
65 | unsigned long cpu_flags; | ||
66 | |||
67 | PDEBUG("executed.\n"); | ||
68 | |||
69 | instance = (me0600_ext_irq_subdevice_t *) subdevice; | ||
70 | |||
71 | if (flags & ~ME_IO_IRQ_START_DIO_BIT) { | ||
72 | PERROR("Invalid flag specified.\n"); | ||
73 | return ME_ERRNO_INVALID_FLAGS; | ||
74 | } | ||
75 | |||
76 | if (instance->lintno > 1) { | ||
77 | PERROR("Wrong idx=%d.\n", instance->lintno); | ||
78 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
79 | } | ||
80 | |||
81 | if (channel) { | ||
82 | PERROR("Invalid channel specified.\n"); | ||
83 | return ME_ERRNO_INVALID_CHANNEL; | ||
84 | } | ||
85 | |||
86 | if (irq_source != ME_IRQ_SOURCE_DIO_LINE) { | ||
87 | PERROR("Invalid irq source specified.\n"); | ||
88 | return ME_ERRNO_INVALID_IRQ_SOURCE; | ||
89 | } | ||
90 | |||
91 | if (irq_edge != ME_IRQ_EDGE_RISING) { | ||
92 | PERROR("Invalid irq edge specified.\n"); | ||
93 | return ME_ERRNO_INVALID_IRQ_EDGE; | ||
94 | } | ||
95 | |||
96 | ME_SUBDEVICE_ENTER; | ||
97 | |||
98 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
99 | spin_lock(instance->intcsr_lock); | ||
100 | tmp = inl(instance->intcsr); | ||
101 | switch (instance->lintno) { | ||
102 | case 0: | ||
103 | tmp |= | ||
104 | PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL | | ||
105 | PLX_INTCSR_PCI_INT_EN; | ||
106 | break; | ||
107 | case 1: | ||
108 | tmp |= | ||
109 | PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL | | ||
110 | PLX_INTCSR_PCI_INT_EN; | ||
111 | break; | ||
112 | } | ||
113 | outl(tmp, instance->intcsr); | ||
114 | PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp); | ||
115 | spin_unlock(instance->intcsr_lock); | ||
116 | instance->rised = 0; | ||
117 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
118 | |||
119 | ME_SUBDEVICE_EXIT; | ||
120 | |||
121 | return ME_ERRNO_SUCCESS; | ||
122 | } | ||
123 | |||
124 | static int me0600_ext_irq_io_irq_wait(struct me_subdevice *subdevice, | ||
125 | struct file *filep, | ||
126 | int channel, | ||
127 | int *irq_count, | ||
128 | int *value, int time_out, int flags) | ||
129 | { | ||
130 | me0600_ext_irq_subdevice_t *instance; | ||
131 | int err = ME_ERRNO_SUCCESS; | ||
132 | long t = 0; | ||
133 | unsigned long cpu_flags; | ||
134 | |||
135 | PDEBUG("executed.\n"); | ||
136 | |||
137 | instance = (me0600_ext_irq_subdevice_t *) subdevice; | ||
138 | |||
139 | if (flags) { | ||
140 | PERROR("Invalid flag specified.\n"); | ||
141 | return ME_ERRNO_INVALID_FLAGS; | ||
142 | } | ||
143 | |||
144 | if (channel) { | ||
145 | PERROR("Invalid channel specified.\n"); | ||
146 | return ME_ERRNO_INVALID_CHANNEL; | ||
147 | } | ||
148 | |||
149 | if (time_out < 0) { | ||
150 | PERROR("Invalid time_out specified.\n"); | ||
151 | return ME_ERRNO_INVALID_TIMEOUT; | ||
152 | } | ||
153 | |||
154 | if (time_out) { | ||
155 | t = (time_out * HZ) / 1000; | ||
156 | |||
157 | if (t == 0) | ||
158 | t = 1; | ||
159 | } | ||
160 | |||
161 | ME_SUBDEVICE_ENTER; | ||
162 | |||
163 | if (instance->rised <= 0) { | ||
164 | instance->rised = 0; | ||
165 | |||
166 | if (time_out) { | ||
167 | t = wait_event_interruptible_timeout(instance-> | ||
168 | wait_queue, | ||
169 | (instance->rised != | ||
170 | 0), t); | ||
171 | |||
172 | if (t == 0) { | ||
173 | PERROR("Wait on interrupt timed out.\n"); | ||
174 | err = ME_ERRNO_TIMEOUT; | ||
175 | } | ||
176 | } else { | ||
177 | wait_event_interruptible(instance->wait_queue, | ||
178 | (instance->rised != 0)); | ||
179 | } | ||
180 | |||
181 | if (instance->rised < 0) { | ||
182 | PERROR("Wait on interrupt aborted by user.\n"); | ||
183 | err = ME_ERRNO_CANCELLED; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | if (signal_pending(current)) { | ||
188 | PERROR("Wait on interrupt aborted by signal.\n"); | ||
189 | err = ME_ERRNO_SIGNAL; | ||
190 | } | ||
191 | |||
192 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
193 | instance->rised = 0; | ||
194 | *irq_count = instance->n; | ||
195 | *value = 1; | ||
196 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
197 | |||
198 | ME_SUBDEVICE_EXIT; | ||
199 | |||
200 | return err; | ||
201 | } | ||
202 | |||
203 | static int me0600_ext_irq_io_irq_stop(struct me_subdevice *subdevice, | ||
204 | struct file *filep, | ||
205 | int channel, int flags) | ||
206 | { | ||
207 | me0600_ext_irq_subdevice_t *instance; | ||
208 | int err = ME_ERRNO_SUCCESS; | ||
209 | uint32_t tmp; | ||
210 | unsigned long cpu_flags; | ||
211 | |||
212 | PDEBUG("executed.\n"); | ||
213 | |||
214 | instance = (me0600_ext_irq_subdevice_t *) subdevice; | ||
215 | |||
216 | if (flags) { | ||
217 | PERROR("Invalid flag specified.\n"); | ||
218 | return ME_ERRNO_INVALID_FLAGS; | ||
219 | } | ||
220 | |||
221 | if (instance->lintno > 1) { | ||
222 | PERROR("Wrong idx=%d.\n", instance->lintno); | ||
223 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
224 | } | ||
225 | |||
226 | if (channel) { | ||
227 | PERROR("Invalid channel specified.\n"); | ||
228 | return ME_ERRNO_INVALID_CHANNEL; | ||
229 | } | ||
230 | |||
231 | ME_SUBDEVICE_ENTER; | ||
232 | |||
233 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
234 | spin_lock(instance->intcsr_lock); | ||
235 | tmp = inl(instance->intcsr); | ||
236 | switch (instance->lintno) { | ||
237 | case 0: | ||
238 | tmp &= ~PLX_INTCSR_LOCAL_INT1_EN; | ||
239 | break; | ||
240 | case 1: | ||
241 | tmp &= ~PLX_INTCSR_LOCAL_INT2_EN; | ||
242 | break; | ||
243 | } | ||
244 | outl(tmp, instance->intcsr); | ||
245 | PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp); | ||
246 | spin_unlock(instance->intcsr_lock); | ||
247 | instance->rised = -1; | ||
248 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
249 | wake_up_interruptible_all(&instance->wait_queue); | ||
250 | |||
251 | ME_SUBDEVICE_EXIT; | ||
252 | |||
253 | return err; | ||
254 | } | ||
255 | |||
256 | static int me0600_ext_irq_io_reset_subdevice(struct me_subdevice *subdevice, | ||
257 | struct file *filep, int flags) | ||
258 | { | ||
259 | me0600_ext_irq_subdevice_t *instance; | ||
260 | uint32_t tmp; | ||
261 | unsigned long cpu_flags; | ||
262 | |||
263 | PDEBUG("executed.\n"); | ||
264 | |||
265 | instance = (me0600_ext_irq_subdevice_t *) subdevice; | ||
266 | |||
267 | if (flags) { | ||
268 | PERROR("Invalid flag specified.\n"); | ||
269 | return ME_ERRNO_INVALID_FLAGS; | ||
270 | } | ||
271 | |||
272 | ME_SUBDEVICE_ENTER; | ||
273 | |||
274 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
275 | spin_lock(instance->intcsr_lock); | ||
276 | tmp = inl(instance->intcsr); | ||
277 | switch (instance->lintno) { | ||
278 | case 0: | ||
279 | tmp |= PLX_INTCSR_LOCAL_INT1_POL | PLX_INTCSR_PCI_INT_EN; | ||
280 | tmp &= ~PLX_INTCSR_LOCAL_INT1_EN; | ||
281 | break; | ||
282 | case 1: | ||
283 | tmp |= PLX_INTCSR_LOCAL_INT2_POL | PLX_INTCSR_PCI_INT_EN; | ||
284 | tmp &= ~PLX_INTCSR_LOCAL_INT2_EN; | ||
285 | break; | ||
286 | } | ||
287 | outl(tmp, instance->intcsr); | ||
288 | PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp); | ||
289 | spin_unlock(instance->intcsr_lock); | ||
290 | |||
291 | instance->rised = -1; | ||
292 | instance->n = 0; | ||
293 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
294 | wake_up_interruptible_all(&instance->wait_queue); | ||
295 | |||
296 | ME_SUBDEVICE_EXIT; | ||
297 | |||
298 | return ME_ERRNO_SUCCESS; | ||
299 | } | ||
300 | |||
301 | static int me0600_ext_irq_query_number_channels(struct me_subdevice *subdevice, | ||
302 | int *number) | ||
303 | { | ||
304 | PDEBUG("executed.\n"); | ||
305 | *number = 1; | ||
306 | return ME_ERRNO_SUCCESS; | ||
307 | } | ||
308 | |||
309 | static int me0600_ext_irq_query_subdevice_type(struct me_subdevice *subdevice, | ||
310 | int *type, int *subtype) | ||
311 | { | ||
312 | PDEBUG("executed.\n"); | ||
313 | *type = ME_TYPE_EXT_IRQ; | ||
314 | *subtype = ME_SUBTYPE_SINGLE; | ||
315 | return ME_ERRNO_SUCCESS; | ||
316 | } | ||
317 | |||
318 | static int me0600_ext_irq_query_subdevice_caps(struct me_subdevice *subdevice, | ||
319 | int *caps) | ||
320 | { | ||
321 | PDEBUG("executed.\n"); | ||
322 | *caps = ME_CAPS_EXT_IRQ_EDGE_RISING; | ||
323 | return ME_ERRNO_SUCCESS; | ||
324 | } | ||
325 | |||
326 | static void me0600_ext_irq_destructor(struct me_subdevice *subdevice) | ||
327 | { | ||
328 | me0600_ext_irq_subdevice_t *instance; | ||
329 | |||
330 | PDEBUG("executed.\n"); | ||
331 | |||
332 | instance = (me0600_ext_irq_subdevice_t *) subdevice; | ||
333 | |||
334 | free_irq(instance->irq, (void *)instance); | ||
335 | me_subdevice_deinit(&instance->base); | ||
336 | kfree(instance); | ||
337 | } | ||
338 | |||
339 | static irqreturn_t me0600_isr(int irq, void *dev_id) | ||
340 | { | ||
341 | me0600_ext_irq_subdevice_t *instance; | ||
342 | uint32_t status; | ||
343 | uint32_t mask = PLX_INTCSR_PCI_INT_EN; | ||
344 | irqreturn_t ret = IRQ_HANDLED; | ||
345 | |||
346 | instance = (me0600_ext_irq_subdevice_t *) dev_id; | ||
347 | |||
348 | if (irq != instance->irq) { | ||
349 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
350 | return IRQ_NONE; | ||
351 | } | ||
352 | |||
353 | PDEBUG("executed.\n"); | ||
354 | |||
355 | if (instance->lintno > 1) { | ||
356 | PERROR_CRITICAL | ||
357 | ("%s():Wrong subdevice index=%d plx:irq_status_reg=0x%04X.\n", | ||
358 | __func__, instance->lintno, inl(instance->intcsr)); | ||
359 | return IRQ_NONE; | ||
360 | } | ||
361 | |||
362 | spin_lock(&instance->subdevice_lock); | ||
363 | spin_lock(instance->intcsr_lock); | ||
364 | status = inl(instance->intcsr); | ||
365 | switch (instance->lintno) { | ||
366 | case 0: | ||
367 | mask |= PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_LOCAL_INT1_EN; | ||
368 | break; | ||
369 | case 1: | ||
370 | mask |= PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_LOCAL_INT2_EN; | ||
371 | break; | ||
372 | } | ||
373 | |||
374 | if ((status & mask) == mask) { | ||
375 | instance->rised = 1; | ||
376 | instance->n++; | ||
377 | inb(instance->reset_reg); | ||
378 | PDEBUG("Interrupt detected.\n"); | ||
379 | } else { | ||
380 | PINFO | ||
381 | ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n", | ||
382 | jiffies, __func__, status); | ||
383 | ret = IRQ_NONE; | ||
384 | } | ||
385 | spin_unlock(instance->intcsr_lock); | ||
386 | spin_unlock(&instance->subdevice_lock); | ||
387 | |||
388 | wake_up_interruptible_all(&instance->wait_queue); | ||
389 | |||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | me0600_ext_irq_subdevice_t *me0600_ext_irq_constructor(uint32_t plx_reg_base, | ||
394 | uint32_t me0600_reg_base, | ||
395 | spinlock_t *intcsr_lock, | ||
396 | unsigned ext_irq_idx, | ||
397 | int irq) | ||
398 | { | ||
399 | me0600_ext_irq_subdevice_t *subdevice; | ||
400 | int err; | ||
401 | |||
402 | PDEBUG("executed.\n"); | ||
403 | |||
404 | /* Allocate memory for subdevice instance */ | ||
405 | subdevice = kmalloc(sizeof(me0600_ext_irq_subdevice_t), GFP_KERNEL); | ||
406 | |||
407 | if (!subdevice) { | ||
408 | PERROR("Cannot get memory for 630_ext_irq instance.\n"); | ||
409 | return NULL; | ||
410 | } | ||
411 | |||
412 | memset(subdevice, 0, sizeof(me0600_ext_irq_subdevice_t)); | ||
413 | |||
414 | /* Initialize subdevice base class */ | ||
415 | err = me_subdevice_init(&subdevice->base); | ||
416 | |||
417 | if (err) { | ||
418 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
419 | kfree(subdevice); | ||
420 | return NULL; | ||
421 | } | ||
422 | // Initialize spin locks. | ||
423 | spin_lock_init(&subdevice->subdevice_lock); | ||
424 | |||
425 | subdevice->intcsr_lock = intcsr_lock; | ||
426 | |||
427 | /* Initialize wait queue */ | ||
428 | init_waitqueue_head(&subdevice->wait_queue); | ||
429 | |||
430 | subdevice->lintno = ext_irq_idx; | ||
431 | |||
432 | /* Request interrupt line */ | ||
433 | subdevice->irq = irq; | ||
434 | |||
435 | err = request_irq(subdevice->irq, me0600_isr, | ||
436 | IRQF_DISABLED | IRQF_SHARED, | ||
437 | ME0600_NAME, (void *)subdevice); | ||
438 | |||
439 | if (err) { | ||
440 | PERROR("Cannot get interrupt line.\n"); | ||
441 | kfree(subdevice); | ||
442 | return NULL; | ||
443 | } | ||
444 | PINFO("Registered irq=%d.\n", subdevice->irq); | ||
445 | |||
446 | /* Initialize registers */ | ||
447 | subdevice->intcsr = plx_reg_base + PLX_INTCSR; | ||
448 | subdevice->reset_reg = | ||
449 | me0600_reg_base + ME0600_INT_0_RESET_REG + ext_irq_idx; | ||
450 | |||
451 | /* Initialize the subdevice methods */ | ||
452 | subdevice->base.me_subdevice_io_irq_start = me0600_ext_irq_io_irq_start; | ||
453 | subdevice->base.me_subdevice_io_irq_wait = me0600_ext_irq_io_irq_wait; | ||
454 | subdevice->base.me_subdevice_io_irq_stop = me0600_ext_irq_io_irq_stop; | ||
455 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
456 | me0600_ext_irq_io_reset_subdevice; | ||
457 | subdevice->base.me_subdevice_query_number_channels = | ||
458 | me0600_ext_irq_query_number_channels; | ||
459 | subdevice->base.me_subdevice_query_subdevice_type = | ||
460 | me0600_ext_irq_query_subdevice_type; | ||
461 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
462 | me0600_ext_irq_query_subdevice_caps; | ||
463 | subdevice->base.me_subdevice_destructor = me0600_ext_irq_destructor; | ||
464 | |||
465 | subdevice->rised = 0; | ||
466 | subdevice->n = 0; | ||
467 | |||
468 | return subdevice; | ||
469 | } | ||
diff --git a/drivers/staging/meilhaus/me0600_ext_irq.h b/drivers/staging/meilhaus/me0600_ext_irq.h deleted file mode 100644 index f5f2204b49a0..000000000000 --- a/drivers/staging/meilhaus/me0600_ext_irq.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_ext_irq.h | ||
3 | * | ||
4 | * @brief ME-630 external interrupt implementation. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME0600_EXT_IRQ_H_ | ||
10 | #define _ME0600_EXT_IRQ_H_ | ||
11 | |||
12 | #include <linux/sched.h> | ||
13 | |||
14 | #include "mesubdevice.h" | ||
15 | #include "meslock.h" | ||
16 | |||
17 | #ifdef __KERNEL__ | ||
18 | |||
19 | /** | ||
20 | * @brief The ME-630 external interrupt subdevice class. | ||
21 | */ | ||
22 | typedef struct me0600_ext_irq_subdevice { | ||
23 | /* Inheritance */ | ||
24 | me_subdevice_t base; /**< The subdevice base class. */ | ||
25 | |||
26 | /* Attributes */ | ||
27 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
28 | spinlock_t *intcsr_lock; /**< Spin lock to protect #intcsr. */ | ||
29 | |||
30 | wait_queue_head_t wait_queue; /**< Queue to put on threads waiting for an interrupt. */ | ||
31 | |||
32 | int irq; /**< The irq number assigned by PCI BIOS. */ | ||
33 | int rised; /**< If true an interrupt has occured. */ | ||
34 | unsigned int n; /**< The number of interrupt since the driver was loaded. */ | ||
35 | unsigned int lintno; /**< The number of the local PCI interrupt. */ | ||
36 | |||
37 | uint32_t intcsr; /**< The PLX interrupt control and status register. */ | ||
38 | uint32_t reset_reg; /**< The control register. */ | ||
39 | } me0600_ext_irq_subdevice_t; | ||
40 | |||
41 | /** | ||
42 | * @brief The constructor to generate a ME-630 external interrupt instance. | ||
43 | * | ||
44 | * @param plx_reg_base The register base address of the PLX chip as returned by the PCI BIOS. | ||
45 | * @param me0600_reg_base The register base address of the ME-630 device as returned by the PCI BIOS. | ||
46 | * @param irq The irq assigned by the PCI BIOS. | ||
47 | * | ||
48 | * @return Pointer to new instance on success.\n | ||
49 | * NULL on error. | ||
50 | */ | ||
51 | me0600_ext_irq_subdevice_t *me0600_ext_irq_constructor(uint32_t plx_reg_base, | ||
52 | uint32_t me0600_reg_base, | ||
53 | spinlock_t * intcsr_lock, | ||
54 | unsigned int ext_irq_idx, | ||
55 | int irq); | ||
56 | |||
57 | #endif | ||
58 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_ext_irq_reg.h b/drivers/staging/meilhaus/me0600_ext_irq_reg.h deleted file mode 100644 index f6198fa6d2b2..000000000000 --- a/drivers/staging/meilhaus/me0600_ext_irq_reg.h +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_ext_irq_reg.h | ||
3 | * | ||
4 | * @brief ME-630 external interrupt register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME0600_EXT_IRQ_REG_H_ | ||
10 | #define _ME0600_EXT_IRQ_REG_H_ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | |||
14 | #define ME0600_INT_0_RESET_REG 0x0005 | ||
15 | #define ME0600_INT_1_RESET_REG 0x0006 | ||
16 | |||
17 | #endif | ||
18 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_optoi.c b/drivers/staging/meilhaus/me0600_optoi.c deleted file mode 100644 index 43f710ffd278..000000000000 --- a/drivers/staging/meilhaus/me0600_optoi.c +++ /dev/null | |||
@@ -1,243 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_optoi.c | ||
3 | * | ||
4 | * @brief ME-630 Optoisolated input subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me0600_optoi_reg.h" | ||
48 | #include "me0600_optoi.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me0600_optoi_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | |||
62 | if (flags) { | ||
63 | PERROR("Invalid flag specified.\n"); | ||
64 | return ME_ERRNO_INVALID_FLAGS; | ||
65 | } | ||
66 | |||
67 | PDEBUG("executed.\n"); | ||
68 | return ME_ERRNO_SUCCESS; | ||
69 | } | ||
70 | |||
71 | static int me0600_optoi_io_single_config(me_subdevice_t *subdevice, | ||
72 | struct file *filep, | ||
73 | int channel, | ||
74 | int single_config, | ||
75 | int ref, | ||
76 | int trig_chan, | ||
77 | int trig_type, | ||
78 | int trig_edge, int flags) | ||
79 | { | ||
80 | me0600_optoi_subdevice_t *instance; | ||
81 | int err = ME_ERRNO_SUCCESS; | ||
82 | |||
83 | PDEBUG("executed.\n"); | ||
84 | |||
85 | instance = (me0600_optoi_subdevice_t *) subdevice; | ||
86 | |||
87 | ME_SUBDEVICE_ENTER; | ||
88 | |||
89 | spin_lock(&instance->subdevice_lock); | ||
90 | |||
91 | switch (flags) { | ||
92 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
93 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
94 | if (channel == 0) { | ||
95 | if (single_config != ME_SINGLE_CONFIG_DIO_INPUT) { | ||
96 | PERROR("Invalid port direction specified.\n"); | ||
97 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
98 | } | ||
99 | } else { | ||
100 | PERROR("Invalid channel specified.\n"); | ||
101 | err = ME_ERRNO_INVALID_CHANNEL; | ||
102 | } | ||
103 | |||
104 | break; | ||
105 | |||
106 | default: | ||
107 | PERROR("Invalid flags specified.\n"); | ||
108 | |||
109 | err = ME_ERRNO_INVALID_FLAGS; | ||
110 | |||
111 | break; | ||
112 | } | ||
113 | |||
114 | spin_unlock(&instance->subdevice_lock); | ||
115 | |||
116 | ME_SUBDEVICE_EXIT; | ||
117 | |||
118 | return err; | ||
119 | } | ||
120 | |||
121 | static int me0600_optoi_io_single_read(me_subdevice_t *subdevice, | ||
122 | struct file *filep, | ||
123 | int channel, | ||
124 | int *value, int time_out, int flags) | ||
125 | { | ||
126 | me0600_optoi_subdevice_t *instance; | ||
127 | int err = ME_ERRNO_SUCCESS; | ||
128 | |||
129 | PDEBUG("executed.\n"); | ||
130 | |||
131 | instance = (me0600_optoi_subdevice_t *) subdevice; | ||
132 | |||
133 | ME_SUBDEVICE_ENTER; | ||
134 | |||
135 | spin_lock(&instance->subdevice_lock); | ||
136 | |||
137 | switch (flags) { | ||
138 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
139 | if ((channel >= 0) && (channel < 8)) { | ||
140 | *value = inb(instance->port_reg) & (0x1 << channel); | ||
141 | } else { | ||
142 | PERROR("Invalid bit number specified.\n"); | ||
143 | err = ME_ERRNO_INVALID_CHANNEL; | ||
144 | } | ||
145 | |||
146 | break; | ||
147 | |||
148 | case ME_IO_SINGLE_NO_FLAGS: | ||
149 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
150 | if (channel == 0) { | ||
151 | *value = inb(instance->port_reg); | ||
152 | } else { | ||
153 | PERROR("Invalid byte number specified.\n"); | ||
154 | err = ME_ERRNO_INVALID_CHANNEL; | ||
155 | } | ||
156 | |||
157 | break; | ||
158 | |||
159 | default: | ||
160 | PERROR("Invalid flags specified.\n"); | ||
161 | |||
162 | err = ME_ERRNO_INVALID_FLAGS; | ||
163 | } | ||
164 | |||
165 | spin_unlock(&instance->subdevice_lock); | ||
166 | |||
167 | ME_SUBDEVICE_EXIT; | ||
168 | |||
169 | return err; | ||
170 | } | ||
171 | |||
172 | static int me0600_optoi_query_number_channels(me_subdevice_t *subdevice, | ||
173 | int *number) | ||
174 | { | ||
175 | PDEBUG("executed.\n"); | ||
176 | *number = 8; | ||
177 | return ME_ERRNO_SUCCESS; | ||
178 | } | ||
179 | |||
180 | static int me0600_optoi_query_subdevice_type(me_subdevice_t *subdevice, | ||
181 | int *type, int *subtype) | ||
182 | { | ||
183 | PDEBUG("executed.\n"); | ||
184 | *type = ME_TYPE_DI; | ||
185 | *subtype = ME_SUBTYPE_SINGLE; | ||
186 | return ME_ERRNO_SUCCESS; | ||
187 | } | ||
188 | |||
189 | static int me0600_optoi_query_subdevice_caps(me_subdevice_t *subdevice, | ||
190 | int *caps) | ||
191 | { | ||
192 | PDEBUG("executed.\n"); | ||
193 | *caps = 0; | ||
194 | return ME_ERRNO_SUCCESS; | ||
195 | } | ||
196 | |||
197 | me0600_optoi_subdevice_t *me0600_optoi_constructor(uint32_t reg_base) | ||
198 | { | ||
199 | me0600_optoi_subdevice_t *subdevice; | ||
200 | int err; | ||
201 | |||
202 | PDEBUG("executed.\n"); | ||
203 | |||
204 | /* Allocate memory for subdevice instance */ | ||
205 | subdevice = kmalloc(sizeof(me0600_optoi_subdevice_t), GFP_KERNEL); | ||
206 | |||
207 | if (!subdevice) { | ||
208 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
209 | return NULL; | ||
210 | } | ||
211 | |||
212 | memset(subdevice, 0, sizeof(me0600_optoi_subdevice_t)); | ||
213 | |||
214 | /* Initialize subdevice base class */ | ||
215 | err = me_subdevice_init(&subdevice->base); | ||
216 | |||
217 | if (err) { | ||
218 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
219 | kfree(subdevice); | ||
220 | return NULL; | ||
221 | } | ||
222 | /* Initialize spin locks. */ | ||
223 | spin_lock_init(&subdevice->subdevice_lock); | ||
224 | |||
225 | /* Save the subdevice index */ | ||
226 | subdevice->port_reg = reg_base + ME0600_OPTO_INPUT_REG; | ||
227 | |||
228 | /* Overload base class methods. */ | ||
229 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
230 | me0600_optoi_io_reset_subdevice; | ||
231 | subdevice->base.me_subdevice_io_single_config = | ||
232 | me0600_optoi_io_single_config; | ||
233 | subdevice->base.me_subdevice_io_single_read = | ||
234 | me0600_optoi_io_single_read; | ||
235 | subdevice->base.me_subdevice_query_number_channels = | ||
236 | me0600_optoi_query_number_channels; | ||
237 | subdevice->base.me_subdevice_query_subdevice_type = | ||
238 | me0600_optoi_query_subdevice_type; | ||
239 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
240 | me0600_optoi_query_subdevice_caps; | ||
241 | |||
242 | return subdevice; | ||
243 | } | ||
diff --git a/drivers/staging/meilhaus/me0600_optoi.h b/drivers/staging/meilhaus/me0600_optoi.h deleted file mode 100644 index e7e69bcde9c9..000000000000 --- a/drivers/staging/meilhaus/me0600_optoi.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_optoi.h | ||
3 | * | ||
4 | * @brief ME-630 Optoisolated input subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_OPTOI_H_ | ||
28 | #define _ME0600_OPTOI_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me0600_optoi_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | |||
44 | uint32_t port_reg; /**< Register holding the port status. */ | ||
45 | } me0600_optoi_subdevice_t; | ||
46 | |||
47 | /** | ||
48 | * @brief The constructor to generate a ME-630 Optoisolated input subdevice instance. | ||
49 | * | ||
50 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
51 | * | ||
52 | * @return Pointer to new instance on success.\n | ||
53 | * NULL on error. | ||
54 | */ | ||
55 | me0600_optoi_subdevice_t *me0600_optoi_constructor(uint32_t reg_base); | ||
56 | |||
57 | #endif | ||
58 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_optoi_reg.h b/drivers/staging/meilhaus/me0600_optoi_reg.h deleted file mode 100644 index e0bc45054000..000000000000 --- a/drivers/staging/meilhaus/me0600_optoi_reg.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_optoi_reg.h | ||
3 | * | ||
4 | * @brief ME-630 Optoisolated input subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_OPTOI_REG_H_ | ||
28 | #define _ME0600_OPTOI_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME0600_OPTO_INPUT_REG 0x0004 | ||
33 | |||
34 | #endif | ||
35 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_relay.c b/drivers/staging/meilhaus/me0600_relay.c deleted file mode 100644 index 03835e3df254..000000000000 --- a/drivers/staging/meilhaus/me0600_relay.c +++ /dev/null | |||
@@ -1,359 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_relay.c | ||
3 | * | ||
4 | * @brief ME-630 relay subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me0600_relay_reg.h" | ||
48 | #include "me0600_relay.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me0600_relay_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | me0600_relay_subdevice_t *instance; | ||
62 | |||
63 | PDEBUG("executed.\n"); | ||
64 | |||
65 | instance = (me0600_relay_subdevice_t *) subdevice; | ||
66 | |||
67 | if (flags) { | ||
68 | PERROR("Invalid flag specified.\n"); | ||
69 | return ME_ERRNO_INVALID_FLAGS; | ||
70 | } | ||
71 | |||
72 | ME_SUBDEVICE_ENTER; | ||
73 | |||
74 | spin_lock(&instance->subdevice_lock); | ||
75 | outb(0x0, instance->port_0_reg); | ||
76 | PDEBUG_REG("port_0_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
77 | instance->port_0_reg - instance->reg_base, 0); | ||
78 | outb(0x0, instance->port_1_reg); | ||
79 | PDEBUG_REG("port_1_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
80 | instance->port_1_reg - instance->reg_base, 0); | ||
81 | spin_unlock(&instance->subdevice_lock); | ||
82 | |||
83 | ME_SUBDEVICE_EXIT; | ||
84 | |||
85 | return ME_ERRNO_SUCCESS; | ||
86 | } | ||
87 | |||
88 | static int me0600_relay_io_single_config(me_subdevice_t *subdevice, | ||
89 | struct file *filep, | ||
90 | int channel, | ||
91 | int single_config, | ||
92 | int ref, | ||
93 | int trig_chan, | ||
94 | int trig_type, | ||
95 | int trig_edge, int flags) | ||
96 | { | ||
97 | me0600_relay_subdevice_t *instance; | ||
98 | int err = ME_ERRNO_SUCCESS; | ||
99 | |||
100 | PDEBUG("executed.\n"); | ||
101 | |||
102 | instance = (me0600_relay_subdevice_t *) subdevice; | ||
103 | |||
104 | ME_SUBDEVICE_ENTER; | ||
105 | |||
106 | spin_lock(&instance->subdevice_lock); | ||
107 | |||
108 | switch (flags) { | ||
109 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
110 | case ME_IO_SINGLE_CONFIG_DIO_WORD: | ||
111 | if (channel == 0) { | ||
112 | if (single_config != ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
113 | PERROR("Invalid word direction specified.\n"); | ||
114 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
115 | } | ||
116 | } else { | ||
117 | PERROR("Invalid channel specified.\n"); | ||
118 | err = ME_ERRNO_INVALID_CHANNEL; | ||
119 | } | ||
120 | |||
121 | break; | ||
122 | |||
123 | default: | ||
124 | PERROR("Invalid flags specified.\n"); | ||
125 | |||
126 | err = ME_ERRNO_INVALID_FLAGS; | ||
127 | |||
128 | break; | ||
129 | } | ||
130 | |||
131 | spin_unlock(&instance->subdevice_lock); | ||
132 | |||
133 | ME_SUBDEVICE_EXIT; | ||
134 | |||
135 | return err; | ||
136 | } | ||
137 | |||
138 | static int me0600_relay_io_single_read(me_subdevice_t *subdevice, | ||
139 | struct file *filep, | ||
140 | int channel, | ||
141 | int *value, int time_out, int flags) | ||
142 | { | ||
143 | me0600_relay_subdevice_t *instance; | ||
144 | int err = ME_ERRNO_SUCCESS; | ||
145 | |||
146 | PDEBUG("executed.\n"); | ||
147 | |||
148 | instance = (me0600_relay_subdevice_t *) subdevice; | ||
149 | |||
150 | ME_SUBDEVICE_ENTER; | ||
151 | |||
152 | spin_lock(&instance->subdevice_lock); | ||
153 | |||
154 | switch (flags) { | ||
155 | |||
156 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
157 | if ((channel >= 0) && (channel < 8)) { | ||
158 | *value = inb(instance->port_0_reg) & (0x1 << channel); | ||
159 | } else if ((channel >= 8) && (channel < 16)) { | ||
160 | *value = | ||
161 | inb(instance->port_1_reg) & (0x1 << (channel - 8)); | ||
162 | } else { | ||
163 | PERROR("Invalid bit number specified.\n"); | ||
164 | err = ME_ERRNO_INVALID_CHANNEL; | ||
165 | } | ||
166 | |||
167 | break; | ||
168 | |||
169 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
170 | if (channel == 0) { | ||
171 | *value = inb(instance->port_0_reg); | ||
172 | } else if (channel == 1) { | ||
173 | *value = inb(instance->port_1_reg); | ||
174 | } else { | ||
175 | PERROR("Invalid byte number specified.\n"); | ||
176 | err = ME_ERRNO_INVALID_CHANNEL; | ||
177 | } | ||
178 | |||
179 | break; | ||
180 | |||
181 | case ME_IO_SINGLE_NO_FLAGS: | ||
182 | case ME_IO_SINGLE_TYPE_DIO_WORD: | ||
183 | if (channel == 0) { | ||
184 | *value = (uint32_t) inb(instance->port_1_reg) << 8; | ||
185 | *value |= inb(instance->port_0_reg); | ||
186 | } else { | ||
187 | PERROR("Invalid word number specified.\n"); | ||
188 | err = ME_ERRNO_INVALID_CHANNEL; | ||
189 | } | ||
190 | |||
191 | break; | ||
192 | |||
193 | default: | ||
194 | PERROR("Invalid flags specified.\n"); | ||
195 | |||
196 | err = ME_ERRNO_INVALID_FLAGS; | ||
197 | } | ||
198 | |||
199 | spin_unlock(&instance->subdevice_lock); | ||
200 | |||
201 | ME_SUBDEVICE_EXIT; | ||
202 | |||
203 | return err; | ||
204 | } | ||
205 | |||
206 | static int me0600_relay_io_single_write(me_subdevice_t *subdevice, | ||
207 | struct file *filep, | ||
208 | int channel, | ||
209 | int value, int time_out, int flags) | ||
210 | { | ||
211 | me0600_relay_subdevice_t *instance; | ||
212 | int err = ME_ERRNO_SUCCESS; | ||
213 | uint8_t state; | ||
214 | |||
215 | PDEBUG("executed.\n"); | ||
216 | |||
217 | instance = (me0600_relay_subdevice_t *) subdevice; | ||
218 | |||
219 | ME_SUBDEVICE_ENTER; | ||
220 | |||
221 | spin_lock(&instance->subdevice_lock); | ||
222 | |||
223 | switch (flags) { | ||
224 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
225 | if ((channel >= 0) && (channel < 8)) { | ||
226 | state = inb(instance->port_0_reg); | ||
227 | state = | ||
228 | value ? (state | (0x1 << channel)) : (state & | ||
229 | ~(0x1 << | ||
230 | channel)); | ||
231 | outb(state, instance->port_0_reg); | ||
232 | } else if ((channel >= 8) && (channel < 16)) { | ||
233 | state = inb(instance->port_1_reg); | ||
234 | state = | ||
235 | value ? (state | (0x1 << (channel - 8))) : (state & | ||
236 | ~(0x1 << | ||
237 | (channel | ||
238 | - | ||
239 | 8))); | ||
240 | outb(state, instance->port_1_reg); | ||
241 | } else { | ||
242 | PERROR("Invalid bit number specified.\n"); | ||
243 | err = ME_ERRNO_INVALID_CHANNEL; | ||
244 | } | ||
245 | break; | ||
246 | |||
247 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
248 | if (channel == 0) { | ||
249 | outb(value, instance->port_0_reg); | ||
250 | } else if (channel == 1) { | ||
251 | outb(value, instance->port_1_reg); | ||
252 | } else { | ||
253 | PERROR("Invalid byte number specified.\n"); | ||
254 | err = ME_ERRNO_INVALID_CHANNEL; | ||
255 | } | ||
256 | break; | ||
257 | |||
258 | case ME_IO_SINGLE_NO_FLAGS: | ||
259 | case ME_IO_SINGLE_TYPE_DIO_WORD: | ||
260 | if (channel == 0) { | ||
261 | outb(value, instance->port_0_reg); | ||
262 | outb(value >> 8, instance->port_1_reg); | ||
263 | } else { | ||
264 | PERROR("Invalid word number specified.\n"); | ||
265 | err = ME_ERRNO_INVALID_CHANNEL; | ||
266 | } | ||
267 | break; | ||
268 | |||
269 | default: | ||
270 | PERROR("Invalid flags specified.\n"); | ||
271 | err = ME_ERRNO_INVALID_FLAGS; | ||
272 | break; | ||
273 | } | ||
274 | |||
275 | spin_unlock(&instance->subdevice_lock); | ||
276 | |||
277 | ME_SUBDEVICE_EXIT; | ||
278 | |||
279 | return err; | ||
280 | } | ||
281 | |||
282 | static int me0600_relay_query_number_channels(me_subdevice_t *subdevice, | ||
283 | int *number) | ||
284 | { | ||
285 | PDEBUG("executed.\n"); | ||
286 | *number = 16; | ||
287 | return ME_ERRNO_SUCCESS; | ||
288 | } | ||
289 | |||
290 | static int me0600_relay_query_subdevice_type(me_subdevice_t *subdevice, | ||
291 | int *type, int *subtype) | ||
292 | { | ||
293 | PDEBUG("executed.\n"); | ||
294 | *type = ME_TYPE_DO; | ||
295 | *subtype = ME_SUBTYPE_SINGLE; | ||
296 | return ME_ERRNO_SUCCESS; | ||
297 | } | ||
298 | |||
299 | static int me0600_relay_query_subdevice_caps(me_subdevice_t *subdevice, | ||
300 | int *caps) | ||
301 | { | ||
302 | PDEBUG("executed.\n"); | ||
303 | *caps = 0; | ||
304 | return ME_ERRNO_SUCCESS; | ||
305 | } | ||
306 | |||
307 | me0600_relay_subdevice_t *me0600_relay_constructor(uint32_t reg_base) | ||
308 | { | ||
309 | me0600_relay_subdevice_t *subdevice; | ||
310 | int err; | ||
311 | |||
312 | PDEBUG("executed.\n"); | ||
313 | |||
314 | /* Allocate memory for subdevice instance */ | ||
315 | subdevice = kmalloc(sizeof(me0600_relay_subdevice_t), GFP_KERNEL); | ||
316 | |||
317 | if (!subdevice) { | ||
318 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
319 | return NULL; | ||
320 | } | ||
321 | |||
322 | memset(subdevice, 0, sizeof(me0600_relay_subdevice_t)); | ||
323 | |||
324 | /* Initialize subdevice base class */ | ||
325 | err = me_subdevice_init(&subdevice->base); | ||
326 | |||
327 | if (err) { | ||
328 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
329 | kfree(subdevice); | ||
330 | return NULL; | ||
331 | } | ||
332 | // Initialize spin locks. | ||
333 | spin_lock_init(&subdevice->subdevice_lock); | ||
334 | |||
335 | /* Save the subdevice index */ | ||
336 | subdevice->port_0_reg = reg_base + ME0600_RELAIS_0_REG; | ||
337 | subdevice->port_1_reg = reg_base + ME0600_RELAIS_1_REG; | ||
338 | #ifdef MEDEBUG_DEBUG_REG | ||
339 | subdevice->reg_base = reg_base; | ||
340 | #endif | ||
341 | |||
342 | /* Overload base class methods. */ | ||
343 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
344 | me0600_relay_io_reset_subdevice; | ||
345 | subdevice->base.me_subdevice_io_single_config = | ||
346 | me0600_relay_io_single_config; | ||
347 | subdevice->base.me_subdevice_io_single_read = | ||
348 | me0600_relay_io_single_read; | ||
349 | subdevice->base.me_subdevice_io_single_write = | ||
350 | me0600_relay_io_single_write; | ||
351 | subdevice->base.me_subdevice_query_number_channels = | ||
352 | me0600_relay_query_number_channels; | ||
353 | subdevice->base.me_subdevice_query_subdevice_type = | ||
354 | me0600_relay_query_subdevice_type; | ||
355 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
356 | me0600_relay_query_subdevice_caps; | ||
357 | |||
358 | return subdevice; | ||
359 | } | ||
diff --git a/drivers/staging/meilhaus/me0600_relay.h b/drivers/staging/meilhaus/me0600_relay.h deleted file mode 100644 index 2ce7dcab8b39..000000000000 --- a/drivers/staging/meilhaus/me0600_relay.h +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_relay.h | ||
3 | * | ||
4 | * @brief ME-630 relay subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_RELAY_H_ | ||
28 | #define _ME0600_RELAY_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me0600_relay_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | |||
44 | unsigned long port_0_reg; /**< Register holding the port status. */ | ||
45 | unsigned long port_1_reg; /**< Register holding the port status. */ | ||
46 | #ifdef MEDEBUG_DEBUG_REG | ||
47 | unsigned long reg_base; | ||
48 | #endif | ||
49 | } me0600_relay_subdevice_t; | ||
50 | |||
51 | /** | ||
52 | * @brief The constructor to generate a ME-630 relay subdevice instance. | ||
53 | * | ||
54 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
55 | * @param ctrl_reg_lock Spin lock protecting the control register. | ||
56 | * | ||
57 | * @return Pointer to new instance on success.\n | ||
58 | * NULL on error. | ||
59 | */ | ||
60 | me0600_relay_subdevice_t *me0600_relay_constructor(uint32_t reg_base); | ||
61 | |||
62 | #endif | ||
63 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_relay_reg.h b/drivers/staging/meilhaus/me0600_relay_reg.h deleted file mode 100644 index ba4db2e223c5..000000000000 --- a/drivers/staging/meilhaus/me0600_relay_reg.h +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_relay_reg.h | ||
3 | * | ||
4 | * @brief ME-630 relay subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_RELAY_REG_H_ | ||
28 | #define _ME0600_RELAY_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME0600_RELAIS_0_REG 0x0001 | ||
33 | #define ME0600_RELAIS_1_REG 0x0002 | ||
34 | |||
35 | #endif | ||
36 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_ttli.c b/drivers/staging/meilhaus/me0600_ttli.c deleted file mode 100644 index 7d970f584cc7..000000000000 --- a/drivers/staging/meilhaus/me0600_ttli.c +++ /dev/null | |||
@@ -1,238 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_ttli.c | ||
3 | * | ||
4 | * @brief ME-630 TTL input subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me0600_ttli_reg.h" | ||
48 | #include "me0600_ttli.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me0600_ttli_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | if (flags) { | ||
62 | PERROR("Invalid flag specified.\n"); | ||
63 | return ME_ERRNO_INVALID_FLAGS; | ||
64 | } | ||
65 | |||
66 | PDEBUG("executed.\n"); | ||
67 | return ME_ERRNO_SUCCESS; | ||
68 | } | ||
69 | |||
70 | static int me0600_ttli_io_single_config(me_subdevice_t *subdevice, | ||
71 | struct file *filep, | ||
72 | int channel, | ||
73 | int single_config, | ||
74 | int ref, | ||
75 | int trig_chan, | ||
76 | int trig_type, int trig_edge, int flags) | ||
77 | { | ||
78 | me0600_ttli_subdevice_t *instance; | ||
79 | int err = ME_ERRNO_SUCCESS; | ||
80 | |||
81 | PDEBUG("executed.\n"); | ||
82 | |||
83 | instance = (me0600_ttli_subdevice_t *) subdevice; | ||
84 | |||
85 | ME_SUBDEVICE_ENTER; | ||
86 | |||
87 | spin_lock(&instance->subdevice_lock); | ||
88 | |||
89 | switch (flags) { | ||
90 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
91 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
92 | if (channel == 0) { | ||
93 | if (single_config != ME_SINGLE_CONFIG_DIO_INPUT) { | ||
94 | PERROR("Invalid port direction specified.\n"); | ||
95 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
96 | } | ||
97 | } else { | ||
98 | PERROR("Invalid channel specified.\n"); | ||
99 | err = ME_ERRNO_INVALID_CHANNEL; | ||
100 | } | ||
101 | |||
102 | break; | ||
103 | |||
104 | default: | ||
105 | PERROR("Invalid flags specified.\n"); | ||
106 | |||
107 | err = ME_ERRNO_INVALID_FLAGS; | ||
108 | |||
109 | break; | ||
110 | } | ||
111 | |||
112 | spin_unlock(&instance->subdevice_lock); | ||
113 | |||
114 | ME_SUBDEVICE_EXIT; | ||
115 | |||
116 | return err; | ||
117 | } | ||
118 | |||
119 | static int me0600_ttli_io_single_read(me_subdevice_t *subdevice, | ||
120 | struct file *filep, | ||
121 | int channel, | ||
122 | int *value, int time_out, int flags) | ||
123 | { | ||
124 | me0600_ttli_subdevice_t *instance; | ||
125 | int err = ME_ERRNO_SUCCESS; | ||
126 | |||
127 | PDEBUG("executed.\n"); | ||
128 | |||
129 | instance = (me0600_ttli_subdevice_t *) subdevice; | ||
130 | |||
131 | ME_SUBDEVICE_ENTER; | ||
132 | |||
133 | spin_lock(&instance->subdevice_lock); | ||
134 | |||
135 | switch (flags) { | ||
136 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
137 | if ((channel >= 0) && (channel < 8)) { | ||
138 | *value = inb(instance->port_reg) & (0x1 << channel); | ||
139 | } else { | ||
140 | PERROR("Invalid bit number specified.\n"); | ||
141 | err = ME_ERRNO_INVALID_CHANNEL; | ||
142 | } | ||
143 | break; | ||
144 | |||
145 | case ME_IO_SINGLE_NO_FLAGS: | ||
146 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
147 | if (channel == 0) { | ||
148 | *value = inb(instance->port_reg); | ||
149 | } else { | ||
150 | PERROR("Invalid byte number specified.\n"); | ||
151 | err = ME_ERRNO_INVALID_CHANNEL; | ||
152 | } | ||
153 | break; | ||
154 | |||
155 | default: | ||
156 | PERROR("Invalid flags specified.\n"); | ||
157 | err = ME_ERRNO_INVALID_FLAGS; | ||
158 | } | ||
159 | |||
160 | spin_unlock(&instance->subdevice_lock); | ||
161 | |||
162 | ME_SUBDEVICE_EXIT; | ||
163 | |||
164 | return err; | ||
165 | } | ||
166 | |||
167 | static int me0600_ttli_query_number_channels(me_subdevice_t *subdevice, | ||
168 | int *number) | ||
169 | { | ||
170 | PDEBUG("executed.\n"); | ||
171 | *number = 8; | ||
172 | return ME_ERRNO_SUCCESS; | ||
173 | } | ||
174 | |||
175 | static int me0600_ttli_query_subdevice_type(me_subdevice_t *subdevice, | ||
176 | int *type, int *subtype) | ||
177 | { | ||
178 | PDEBUG("executed.\n"); | ||
179 | *type = ME_TYPE_DI; | ||
180 | *subtype = ME_SUBTYPE_SINGLE; | ||
181 | return ME_ERRNO_SUCCESS; | ||
182 | } | ||
183 | |||
184 | static int me0600_ttli_query_subdevice_caps(me_subdevice_t *subdevice, | ||
185 | int *caps) | ||
186 | { | ||
187 | PDEBUG("executed.\n"); | ||
188 | *caps = 0; | ||
189 | return ME_ERRNO_SUCCESS; | ||
190 | } | ||
191 | |||
192 | me0600_ttli_subdevice_t *me0600_ttli_constructor(uint32_t reg_base) | ||
193 | { | ||
194 | me0600_ttli_subdevice_t *subdevice; | ||
195 | int err; | ||
196 | |||
197 | PDEBUG("executed.\n"); | ||
198 | |||
199 | /* Allocate memory for subdevice instance */ | ||
200 | subdevice = kmalloc(sizeof(me0600_ttli_subdevice_t), GFP_KERNEL); | ||
201 | |||
202 | if (!subdevice) { | ||
203 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
204 | return NULL; | ||
205 | } | ||
206 | |||
207 | memset(subdevice, 0, sizeof(me0600_ttli_subdevice_t)); | ||
208 | |||
209 | /* Initialize subdevice base class */ | ||
210 | err = me_subdevice_init(&subdevice->base); | ||
211 | |||
212 | if (err) { | ||
213 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
214 | kfree(subdevice); | ||
215 | return NULL; | ||
216 | } | ||
217 | // Initialize spin locks. | ||
218 | spin_lock_init(&subdevice->subdevice_lock); | ||
219 | |||
220 | /* Save the subdevice index */ | ||
221 | subdevice->port_reg = reg_base + ME0600_TTL_INPUT_REG; | ||
222 | |||
223 | /* Overload base class methods. */ | ||
224 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
225 | me0600_ttli_io_reset_subdevice; | ||
226 | subdevice->base.me_subdevice_io_single_config = | ||
227 | me0600_ttli_io_single_config; | ||
228 | subdevice->base.me_subdevice_io_single_read = | ||
229 | me0600_ttli_io_single_read; | ||
230 | subdevice->base.me_subdevice_query_number_channels = | ||
231 | me0600_ttli_query_number_channels; | ||
232 | subdevice->base.me_subdevice_query_subdevice_type = | ||
233 | me0600_ttli_query_subdevice_type; | ||
234 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
235 | me0600_ttli_query_subdevice_caps; | ||
236 | |||
237 | return subdevice; | ||
238 | } | ||
diff --git a/drivers/staging/meilhaus/me0600_ttli.h b/drivers/staging/meilhaus/me0600_ttli.h deleted file mode 100644 index 6c9039614867..000000000000 --- a/drivers/staging/meilhaus/me0600_ttli.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_ttli.h | ||
3 | * | ||
4 | * @brief ME-630 TTL input subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_TTLI_H_ | ||
28 | #define _ME0600_TTLI_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me0600_ttli_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | |||
44 | uint32_t port_reg; /**< Register holding the port status. */ | ||
45 | } me0600_ttli_subdevice_t; | ||
46 | |||
47 | /** | ||
48 | * @brief The constructor to generate a ME-630 TTL input subdevice instance. | ||
49 | * | ||
50 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
51 | * | ||
52 | * @return Pointer to new instance on success.\n | ||
53 | * NULL on error. | ||
54 | */ | ||
55 | me0600_ttli_subdevice_t *me0600_ttli_constructor(uint32_t reg_base); | ||
56 | |||
57 | #endif | ||
58 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0600_ttli_reg.h b/drivers/staging/meilhaus/me0600_ttli_reg.h deleted file mode 100644 index 4f986d160934..000000000000 --- a/drivers/staging/meilhaus/me0600_ttli_reg.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0600_ttli_reg.h | ||
3 | * | ||
4 | * @brief ME-630 TTL input subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0600_TTLI_REG_H_ | ||
28 | #define _ME0600_TTLI_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME0600_TTL_INPUT_REG 0x0003 | ||
33 | |||
34 | #endif | ||
35 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0900_device.c b/drivers/staging/meilhaus/me0900_device.c deleted file mode 100644 index e9c6884b5d23..000000000000 --- a/drivers/staging/meilhaus/me0900_device.c +++ /dev/null | |||
@@ -1,178 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0900_device.c | ||
3 | * | ||
4 | * @brief ME-9x device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include "meids.h" | ||
42 | #include "meerror.h" | ||
43 | #include "mecommon.h" | ||
44 | #include "meinternal.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "medevice.h" | ||
48 | #include "me0900_device.h" | ||
49 | #include "me0900_reg.h" | ||
50 | #include "mesubdevice.h" | ||
51 | #include "me0900_do.h" | ||
52 | #include "me0900_di.h" | ||
53 | |||
54 | me_device_t *me0900_pci_constructor(struct pci_dev *pci_device) | ||
55 | { | ||
56 | me0900_device_t *me0900_device; | ||
57 | me_subdevice_t *subdevice; | ||
58 | unsigned int version_idx; | ||
59 | int err; | ||
60 | int i; | ||
61 | int port_shift; | ||
62 | |||
63 | PDEBUG("executed.\n"); | ||
64 | |||
65 | // Allocate structure for device instance. | ||
66 | me0900_device = kmalloc(sizeof(me0900_device_t), GFP_KERNEL); | ||
67 | |||
68 | if (!me0900_device) { | ||
69 | PERROR("Cannot get memory for device instance.\n"); | ||
70 | return NULL; | ||
71 | } | ||
72 | |||
73 | memset(me0900_device, 0, sizeof(me0900_device_t)); | ||
74 | |||
75 | // Initialize base class structure. | ||
76 | err = me_device_pci_init((me_device_t *) me0900_device, pci_device); | ||
77 | |||
78 | if (err) { | ||
79 | kfree(me0900_device); | ||
80 | PERROR("Cannot initialize device base class.\n"); | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | /* Get the index in the device version information table. */ | ||
85 | version_idx = | ||
86 | me0900_versions_get_device_index(me0900_device->base.info.pci. | ||
87 | device_id); | ||
88 | |||
89 | /* Initialize 8255 chip to desired mode */ | ||
90 | if (me0900_device->base.info.pci.device_id == | ||
91 | PCI_DEVICE_ID_MEILHAUS_ME0940) { | ||
92 | outb(0x9B, | ||
93 | me0900_device->base.info.pci.reg_bases[2] + | ||
94 | ME0900_CTRL_REG); | ||
95 | } else if (me0900_device->base.info.pci.device_id == | ||
96 | PCI_DEVICE_ID_MEILHAUS_ME0950) { | ||
97 | outb(0x89, | ||
98 | me0900_device->base.info.pci.reg_bases[2] + | ||
99 | ME0900_CTRL_REG); | ||
100 | outb(0x00, | ||
101 | me0900_device->base.info.pci.reg_bases[2] + | ||
102 | ME0900_WRITE_ENABLE_REG); | ||
103 | } else if (me0900_device->base.info.pci.device_id == | ||
104 | PCI_DEVICE_ID_MEILHAUS_ME0960) { | ||
105 | outb(0x8B, | ||
106 | me0900_device->base.info.pci.reg_bases[2] + | ||
107 | ME0900_CTRL_REG); | ||
108 | outb(0x00, | ||
109 | me0900_device->base.info.pci.reg_bases[2] + | ||
110 | ME0900_WRITE_ENABLE_REG); | ||
111 | } | ||
112 | |||
113 | port_shift = | ||
114 | (me0900_device->base.info.pci.device_id == | ||
115 | PCI_DEVICE_ID_MEILHAUS_ME0960) ? 1 : 0; | ||
116 | // Create subdevice instances. | ||
117 | |||
118 | for (i = 0; i < me0900_versions[version_idx].di_subdevices; i++) { | ||
119 | subdevice = | ||
120 | (me_subdevice_t *) me0900_di_constructor(me0900_device-> | ||
121 | base.info.pci. | ||
122 | reg_bases[2], | ||
123 | i + port_shift); | ||
124 | |||
125 | if (!subdevice) { | ||
126 | me_device_deinit((me_device_t *) me0900_device); | ||
127 | kfree(me0900_device); | ||
128 | PERROR("Cannot get memory for subdevice.\n"); | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | me_slist_add_subdevice_tail(&me0900_device->base.slist, | ||
133 | subdevice); | ||
134 | } | ||
135 | |||
136 | for (i = 0; i < me0900_versions[version_idx].do_subdevices; i++) { | ||
137 | subdevice = | ||
138 | (me_subdevice_t *) me0900_do_constructor(me0900_device-> | ||
139 | base.info.pci. | ||
140 | reg_bases[2], i); | ||
141 | |||
142 | if (!subdevice) { | ||
143 | me_device_deinit((me_device_t *) me0900_device); | ||
144 | kfree(me0900_device); | ||
145 | PERROR("Cannot get memory for subdevice.\n"); | ||
146 | return NULL; | ||
147 | } | ||
148 | |||
149 | me_slist_add_subdevice_tail(&me0900_device->base.slist, | ||
150 | subdevice); | ||
151 | } | ||
152 | |||
153 | return (me_device_t *) me0900_device; | ||
154 | } | ||
155 | EXPORT_SYMBOL(me0900_pci_constructor); | ||
156 | |||
157 | // Init and exit of module. | ||
158 | |||
159 | static int __init me0900_init(void) | ||
160 | { | ||
161 | PDEBUG("executed.\n."); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static void __exit me0900_exit(void) | ||
166 | { | ||
167 | PDEBUG("executed.\n."); | ||
168 | } | ||
169 | |||
170 | module_init(me0900_init); | ||
171 | module_exit(me0900_exit); | ||
172 | |||
173 | // Administrative stuff for modinfo. | ||
174 | MODULE_AUTHOR | ||
175 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
176 | MODULE_DESCRIPTION("Device Driver Module for ME-9x Device"); | ||
177 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-9x Devices"); | ||
178 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me0900_device.h b/drivers/staging/meilhaus/me0900_device.h deleted file mode 100644 index 53c05e83675d..000000000000 --- a/drivers/staging/meilhaus/me0900_device.h +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0900_device.h | ||
3 | * | ||
4 | * @brief ME-0900 (ME-9x) device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0900_DEVICE_H | ||
28 | #define _ME0900_DEVICE_H | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | /** | ||
38 | * @brief Structure holding ME-0900 (ME-9x) device capabilities. | ||
39 | */ | ||
40 | typedef struct me0900_version { | ||
41 | uint16_t device_id; | ||
42 | unsigned int di_subdevices; | ||
43 | unsigned int do_subdevices; | ||
44 | } me0900_version_t; | ||
45 | |||
46 | /** | ||
47 | * @brief Device capabilities. | ||
48 | */ | ||
49 | static me0900_version_t me0900_versions[] = { | ||
50 | {PCI_DEVICE_ID_MEILHAUS_ME0940, 2, 0}, | ||
51 | {PCI_DEVICE_ID_MEILHAUS_ME0950, 0, 2}, | ||
52 | {PCI_DEVICE_ID_MEILHAUS_ME0960, 1, 1}, | ||
53 | {0}, | ||
54 | }; | ||
55 | |||
56 | #define ME0900_DEVICE_VERSIONS (ARRAY_SIZE(me0900_versions) - 1) /**< Returns the number of entries in #me0900_versions. */ | ||
57 | |||
58 | /** | ||
59 | * @brief Returns the index of the device entry in #me0900_versions. | ||
60 | * | ||
61 | * @param device_id The PCI device id of the device to query. | ||
62 | * @return The index of the device in #me0900_versions. | ||
63 | */ | ||
64 | static inline unsigned int me0900_versions_get_device_index(uint16_t device_id) | ||
65 | { | ||
66 | unsigned int i; | ||
67 | for (i = 0; i < ME0900_DEVICE_VERSIONS; i++) | ||
68 | if (me0900_versions[i].device_id == device_id) | ||
69 | break; | ||
70 | return i; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * @brief The ME-0900 (ME-9x) device class structure. | ||
75 | */ | ||
76 | typedef struct me0900_device { | ||
77 | me_device_t base; /**< The Meilhaus device base class. */ | ||
78 | } me0900_device_t; | ||
79 | |||
80 | /** | ||
81 | * @brief The ME-9x device class constructor. | ||
82 | * | ||
83 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
84 | * | ||
85 | * @return On succes a new ME-0900 (ME-9x) device instance. \n | ||
86 | * NULL on error. | ||
87 | */ | ||
88 | me_device_t *me0900_pci_constructor(struct pci_dev *pci_device) | ||
89 | __attribute__ ((weak)); | ||
90 | |||
91 | #endif | ||
92 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0900_di.c b/drivers/staging/meilhaus/me0900_di.c deleted file mode 100644 index b8c448f58e36..000000000000 --- a/drivers/staging/meilhaus/me0900_di.c +++ /dev/null | |||
@@ -1,245 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0900_di.c | ||
3 | * | ||
4 | * @brief ME-9x digital input subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef __KERNEL__ | ||
28 | # define __KERNEL__ | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Includes | ||
33 | */ | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/slab.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/io.h> | ||
39 | #include <linux/types.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "meids.h" | ||
47 | #include "medebug.h" | ||
48 | #include "meplx_reg.h" | ||
49 | #include "me0900_reg.h" | ||
50 | #include "me0900_di.h" | ||
51 | |||
52 | /* | ||
53 | * Defines | ||
54 | */ | ||
55 | |||
56 | /* | ||
57 | * Functions | ||
58 | */ | ||
59 | |||
60 | static int me0900_di_io_reset_subdevice(struct me_subdevice *subdevice, | ||
61 | struct file *filep, int flags) | ||
62 | { | ||
63 | PDEBUG("executed.\n"); | ||
64 | |||
65 | if (flags) { | ||
66 | PERROR("Invalid flag specified.\n"); | ||
67 | return ME_ERRNO_INVALID_FLAGS; | ||
68 | } | ||
69 | |||
70 | return ME_ERRNO_SUCCESS; | ||
71 | } | ||
72 | |||
73 | static int me0900_di_io_single_config(me_subdevice_t *subdevice, | ||
74 | struct file *filep, | ||
75 | int channel, | ||
76 | int single_config, | ||
77 | int ref, | ||
78 | int trig_chan, | ||
79 | int trig_type, int trig_edge, int flags) | ||
80 | { | ||
81 | me0900_di_subdevice_t *instance; | ||
82 | int err = ME_ERRNO_SUCCESS; | ||
83 | |||
84 | PDEBUG("executed.\n"); | ||
85 | |||
86 | instance = (me0900_di_subdevice_t *) subdevice; | ||
87 | |||
88 | ME_SUBDEVICE_ENTER; | ||
89 | |||
90 | spin_lock(&instance->subdevice_lock); | ||
91 | switch (flags) { | ||
92 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
93 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
94 | if (channel == 0) { | ||
95 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
96 | } else { | ||
97 | PERROR("Invalid byte direction specified.\n"); | ||
98 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
99 | } | ||
100 | } else { | ||
101 | PERROR("Invalid byte number specified.\n"); | ||
102 | err = ME_ERRNO_INVALID_CHANNEL; | ||
103 | } | ||
104 | break; | ||
105 | |||
106 | default: | ||
107 | PERROR("Invalid flags specified.\n"); | ||
108 | err = ME_ERRNO_INVALID_FLAGS; | ||
109 | } | ||
110 | spin_unlock(&instance->subdevice_lock); | ||
111 | |||
112 | ME_SUBDEVICE_EXIT; | ||
113 | |||
114 | return err; | ||
115 | } | ||
116 | |||
117 | static int me0900_di_io_single_read(me_subdevice_t *subdevice, | ||
118 | struct file *filep, | ||
119 | int channel, | ||
120 | int *value, int time_out, int flags) | ||
121 | { | ||
122 | me0900_di_subdevice_t *instance; | ||
123 | int err = ME_ERRNO_SUCCESS; | ||
124 | |||
125 | PDEBUG("executed.\n"); | ||
126 | |||
127 | instance = (me0900_di_subdevice_t *) subdevice; | ||
128 | |||
129 | ME_SUBDEVICE_ENTER; | ||
130 | |||
131 | spin_lock(&instance->subdevice_lock); | ||
132 | switch (flags) { | ||
133 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
134 | if ((channel >= 0) && (channel < 8)) { | ||
135 | *value = (~inb(instance->port_reg)) & (0x1 << channel); | ||
136 | } else { | ||
137 | PERROR("Invalid bit number specified.\n"); | ||
138 | err = ME_ERRNO_INVALID_CHANNEL; | ||
139 | } | ||
140 | break; | ||
141 | |||
142 | case ME_IO_SINGLE_NO_FLAGS: | ||
143 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
144 | if (channel == 0) { | ||
145 | *value = ~inb(instance->port_reg); | ||
146 | } else { | ||
147 | PERROR("Invalid byte number specified.\n"); | ||
148 | err = ME_ERRNO_INVALID_CHANNEL; | ||
149 | } | ||
150 | break; | ||
151 | |||
152 | default: | ||
153 | PERROR("Invalid flags specified.\n"); | ||
154 | err = ME_ERRNO_INVALID_FLAGS; | ||
155 | } | ||
156 | spin_unlock(&instance->subdevice_lock); | ||
157 | |||
158 | ME_SUBDEVICE_EXIT; | ||
159 | |||
160 | return err; | ||
161 | } | ||
162 | |||
163 | static int me0900_di_query_number_channels(me_subdevice_t *subdevice, | ||
164 | int *number) | ||
165 | { | ||
166 | PDEBUG("executed.\n"); | ||
167 | *number = 8; | ||
168 | return ME_ERRNO_SUCCESS; | ||
169 | } | ||
170 | |||
171 | static int me0900_di_query_subdevice_type(me_subdevice_t *subdevice, | ||
172 | int *type, int *subtype) | ||
173 | { | ||
174 | PDEBUG("executed.\n"); | ||
175 | *type = ME_TYPE_DI; | ||
176 | *subtype = ME_SUBTYPE_SINGLE; | ||
177 | return ME_ERRNO_SUCCESS; | ||
178 | } | ||
179 | |||
180 | static int me0900_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
181 | { | ||
182 | PDEBUG("executed.\n"); | ||
183 | *caps = 0; | ||
184 | return ME_ERRNO_SUCCESS; | ||
185 | } | ||
186 | |||
187 | me0900_di_subdevice_t *me0900_di_constructor(uint32_t reg_base, | ||
188 | unsigned int di_idx) | ||
189 | { | ||
190 | me0900_di_subdevice_t *subdevice; | ||
191 | int err; | ||
192 | |||
193 | PDEBUG("executed.\n"); | ||
194 | |||
195 | /* Allocate memory for subdevice instance */ | ||
196 | subdevice = kmalloc(sizeof(me0900_di_subdevice_t), GFP_KERNEL); | ||
197 | |||
198 | if (!subdevice) { | ||
199 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
200 | return NULL; | ||
201 | } | ||
202 | |||
203 | memset(subdevice, 0, sizeof(me0900_di_subdevice_t)); | ||
204 | |||
205 | /* Initialize subdevice base class */ | ||
206 | err = me_subdevice_init(&subdevice->base); | ||
207 | |||
208 | if (err) { | ||
209 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
210 | kfree(subdevice); | ||
211 | return NULL; | ||
212 | } | ||
213 | // Initialize spin locks. | ||
214 | spin_lock_init(&subdevice->subdevice_lock); | ||
215 | |||
216 | /* Save the subdevice index. */ | ||
217 | subdevice->di_idx = di_idx; | ||
218 | |||
219 | /* Initialize registers */ | ||
220 | if (di_idx == 0) { | ||
221 | subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; | ||
222 | subdevice->port_reg = reg_base + ME0900_PORT_A_REG; | ||
223 | } else { | ||
224 | subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; | ||
225 | subdevice->port_reg = reg_base + ME0900_PORT_B_REG; | ||
226 | } | ||
227 | #ifdef MEDEBUG_DEBUG_REG | ||
228 | subdevice->reg_base = reg_base; | ||
229 | #endif | ||
230 | |||
231 | /* Overload base class methods. */ | ||
232 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
233 | me0900_di_io_reset_subdevice; | ||
234 | subdevice->base.me_subdevice_io_single_config = | ||
235 | me0900_di_io_single_config; | ||
236 | subdevice->base.me_subdevice_io_single_read = me0900_di_io_single_read; | ||
237 | subdevice->base.me_subdevice_query_number_channels = | ||
238 | me0900_di_query_number_channels; | ||
239 | subdevice->base.me_subdevice_query_subdevice_type = | ||
240 | me0900_di_query_subdevice_type; | ||
241 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
242 | me0900_di_query_subdevice_caps; | ||
243 | |||
244 | return subdevice; | ||
245 | } | ||
diff --git a/drivers/staging/meilhaus/me0900_di.h b/drivers/staging/meilhaus/me0900_di.h deleted file mode 100644 index 014f1348fc9f..000000000000 --- a/drivers/staging/meilhaus/me0900_di.h +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0900_di.h | ||
3 | * | ||
4 | * @brief ME-9x digital input subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0900_DI_H_ | ||
28 | #define _ME0900_DI_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me0900_di_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | |||
44 | unsigned int di_idx; | ||
45 | |||
46 | unsigned long ctrl_reg; | ||
47 | unsigned long port_reg; | ||
48 | #ifdef MEDEBUG_DEBUG_REG | ||
49 | unsigned long reg_base; | ||
50 | #endif | ||
51 | } me0900_di_subdevice_t; | ||
52 | |||
53 | /** | ||
54 | * @brief The constructor to generate a ME-9x digital input subdevice instance. | ||
55 | * | ||
56 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
57 | * | ||
58 | * @return Pointer to new instance on success.\n | ||
59 | * NULL on error. | ||
60 | */ | ||
61 | me0900_di_subdevice_t *me0900_di_constructor(uint32_t me0900_reg_base, | ||
62 | unsigned int di_idx); | ||
63 | |||
64 | #endif | ||
65 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0900_do.c b/drivers/staging/meilhaus/me0900_do.c deleted file mode 100644 index a2275faf1a0c..000000000000 --- a/drivers/staging/meilhaus/me0900_do.c +++ /dev/null | |||
@@ -1,314 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0900_do.c | ||
3 | * | ||
4 | * @brief ME-9x digital output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef __KERNEL__ | ||
28 | # define __KERNEL__ | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Includes | ||
33 | */ | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/slab.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/io.h> | ||
39 | #include <linux/types.h> | ||
40 | |||
41 | #include "medefines.h" | ||
42 | #include "meinternal.h" | ||
43 | #include "meerror.h" | ||
44 | |||
45 | #include "medebug.h" | ||
46 | #include "me0900_reg.h" | ||
47 | #include "me0900_do.h" | ||
48 | |||
49 | /* | ||
50 | * Defines | ||
51 | */ | ||
52 | |||
53 | /* | ||
54 | * Functions | ||
55 | */ | ||
56 | |||
57 | static int me0900_do_io_reset_subdevice(struct me_subdevice *subdevice, | ||
58 | struct file *filep, int flags) | ||
59 | { | ||
60 | me0900_do_subdevice_t *instance; | ||
61 | |||
62 | PDEBUG("executed.\n"); | ||
63 | |||
64 | instance = (me0900_do_subdevice_t *) subdevice; | ||
65 | |||
66 | if (flags) { | ||
67 | PERROR("Invalid flag specified.\n"); | ||
68 | return ME_ERRNO_INVALID_FLAGS; | ||
69 | } | ||
70 | |||
71 | ME_SUBDEVICE_ENTER; | ||
72 | |||
73 | spin_lock(&instance->subdevice_lock); | ||
74 | outb(0xFF, instance->port_reg); | ||
75 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
76 | instance->port_reg - instance->reg_base, 0xff); | ||
77 | spin_unlock(&instance->subdevice_lock); | ||
78 | |||
79 | ME_SUBDEVICE_EXIT; | ||
80 | |||
81 | return ME_ERRNO_SUCCESS; | ||
82 | } | ||
83 | |||
84 | static int me0900_do_io_single_config(me_subdevice_t *subdevice, | ||
85 | struct file *filep, | ||
86 | int channel, | ||
87 | int single_config, | ||
88 | int ref, | ||
89 | int trig_chan, | ||
90 | int trig_type, int trig_edge, int flags) | ||
91 | { | ||
92 | me0900_do_subdevice_t *instance; | ||
93 | int err = ME_ERRNO_SUCCESS; | ||
94 | |||
95 | PDEBUG("executed.\n"); | ||
96 | |||
97 | instance = (me0900_do_subdevice_t *) subdevice; | ||
98 | |||
99 | ME_SUBDEVICE_ENTER; | ||
100 | |||
101 | spin_lock(&instance->subdevice_lock); | ||
102 | switch (flags) { | ||
103 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
104 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
105 | if (channel == 0) { | ||
106 | if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
107 | } else { | ||
108 | PERROR("Invalid byte direction specified.\n"); | ||
109 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
110 | } | ||
111 | } else { | ||
112 | PERROR("Invalid byte number specified.\n"); | ||
113 | err = ME_ERRNO_INVALID_CHANNEL; | ||
114 | } | ||
115 | break; | ||
116 | |||
117 | default: | ||
118 | PERROR("Invalid flags specified.\n"); | ||
119 | err = ME_ERRNO_INVALID_FLAGS; | ||
120 | } | ||
121 | spin_unlock(&instance->subdevice_lock); | ||
122 | |||
123 | ME_SUBDEVICE_EXIT; | ||
124 | |||
125 | return err; | ||
126 | } | ||
127 | |||
128 | static int me0900_do_io_single_read(me_subdevice_t *subdevice, | ||
129 | struct file *filep, | ||
130 | int channel, | ||
131 | int *value, int time_out, int flags) | ||
132 | { | ||
133 | me0900_do_subdevice_t *instance; | ||
134 | int err = ME_ERRNO_SUCCESS; | ||
135 | |||
136 | PDEBUG("executed.\n"); | ||
137 | |||
138 | instance = (me0900_do_subdevice_t *) subdevice; | ||
139 | |||
140 | ME_SUBDEVICE_ENTER; | ||
141 | |||
142 | spin_lock(&instance->subdevice_lock); | ||
143 | switch (flags) { | ||
144 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
145 | if ((channel >= 0) && (channel < 8)) { | ||
146 | *value = (~inb(instance->port_reg)) & (0x1 << channel); | ||
147 | } else { | ||
148 | PERROR("Invalid bit number specified.\n"); | ||
149 | err = ME_ERRNO_INVALID_CHANNEL; | ||
150 | } | ||
151 | break; | ||
152 | |||
153 | case ME_IO_SINGLE_NO_FLAGS: | ||
154 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
155 | if (channel == 0) { | ||
156 | *value = ~inb(instance->port_reg); | ||
157 | } else { | ||
158 | PERROR("Invalid byte number specified.\n"); | ||
159 | err = ME_ERRNO_INVALID_CHANNEL; | ||
160 | } | ||
161 | break; | ||
162 | |||
163 | default: | ||
164 | PERROR("Invalid flags specified.\n"); | ||
165 | err = ME_ERRNO_INVALID_FLAGS; | ||
166 | } | ||
167 | spin_unlock(&instance->subdevice_lock); | ||
168 | |||
169 | ME_SUBDEVICE_EXIT; | ||
170 | |||
171 | return err; | ||
172 | } | ||
173 | |||
174 | static int me0900_do_io_single_write(me_subdevice_t *subdevice, | ||
175 | struct file *filep, | ||
176 | int channel, | ||
177 | int value, int time_out, int flags) | ||
178 | { | ||
179 | me0900_do_subdevice_t *instance; | ||
180 | int err = ME_ERRNO_SUCCESS; | ||
181 | unsigned long state; | ||
182 | |||
183 | PDEBUG("executed.\n"); | ||
184 | |||
185 | instance = (me0900_do_subdevice_t *) subdevice; | ||
186 | |||
187 | ME_SUBDEVICE_ENTER; | ||
188 | |||
189 | spin_lock(&instance->subdevice_lock); | ||
190 | switch (flags) { | ||
191 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
192 | if ((channel >= 0) && (channel < 8)) { | ||
193 | state = inb(instance->port_reg); | ||
194 | state = | ||
195 | (!value) ? (state | (0x1 << channel)) : (state & | ||
196 | ~(0x1 << | ||
197 | channel)); | ||
198 | outb(state, instance->port_reg); | ||
199 | } else { | ||
200 | PERROR("Invalid bit number specified.\n"); | ||
201 | err = ME_ERRNO_INVALID_CHANNEL; | ||
202 | } | ||
203 | break; | ||
204 | |||
205 | case ME_IO_SINGLE_NO_FLAGS: | ||
206 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
207 | if (channel == 0) { | ||
208 | outb(~(value), instance->port_reg); | ||
209 | } else { | ||
210 | PERROR("Invalid byte number specified.\n"); | ||
211 | err = ME_ERRNO_INVALID_CHANNEL; | ||
212 | } | ||
213 | break; | ||
214 | |||
215 | default: | ||
216 | PERROR("Invalid flags specified.\n"); | ||
217 | err = ME_ERRNO_INVALID_FLAGS; | ||
218 | } | ||
219 | spin_unlock(&instance->subdevice_lock); | ||
220 | |||
221 | ME_SUBDEVICE_EXIT; | ||
222 | |||
223 | return err; | ||
224 | } | ||
225 | |||
226 | static int me0900_do_query_number_channels(me_subdevice_t *subdevice, | ||
227 | int *number) | ||
228 | { | ||
229 | PDEBUG("executed.\n"); | ||
230 | *number = 8; | ||
231 | return ME_ERRNO_SUCCESS; | ||
232 | } | ||
233 | |||
234 | static int me0900_do_query_subdevice_type(me_subdevice_t *subdevice, | ||
235 | int *type, int *subtype) | ||
236 | { | ||
237 | PDEBUG("executed.\n"); | ||
238 | *type = ME_TYPE_DO; | ||
239 | *subtype = ME_SUBTYPE_SINGLE; | ||
240 | return ME_ERRNO_SUCCESS; | ||
241 | } | ||
242 | |||
243 | static int me0900_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
244 | { | ||
245 | PDEBUG("executed.\n"); | ||
246 | *caps = 0; | ||
247 | return ME_ERRNO_SUCCESS; | ||
248 | } | ||
249 | |||
250 | me0900_do_subdevice_t *me0900_do_constructor(uint32_t reg_base, | ||
251 | unsigned int do_idx) | ||
252 | { | ||
253 | me0900_do_subdevice_t *subdevice; | ||
254 | int err; | ||
255 | |||
256 | PDEBUG("executed.\n"); | ||
257 | |||
258 | /* Allocate memory for subdevice instance */ | ||
259 | subdevice = kmalloc(sizeof(me0900_do_subdevice_t), GFP_KERNEL); | ||
260 | |||
261 | if (!subdevice) { | ||
262 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
263 | return NULL; | ||
264 | } | ||
265 | |||
266 | memset(subdevice, 0, sizeof(me0900_do_subdevice_t)); | ||
267 | |||
268 | /* Initialize subdevice base class */ | ||
269 | err = me_subdevice_init(&subdevice->base); | ||
270 | |||
271 | if (err) { | ||
272 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
273 | kfree(subdevice); | ||
274 | return NULL; | ||
275 | } | ||
276 | // Initialize spin locks. | ||
277 | spin_lock_init(&subdevice->subdevice_lock); | ||
278 | |||
279 | /* Save the subdevice index */ | ||
280 | subdevice->do_idx = do_idx; | ||
281 | |||
282 | /* Initialize registers */ | ||
283 | if (do_idx == 0) { | ||
284 | subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; | ||
285 | subdevice->port_reg = reg_base + ME0900_PORT_A_REG; | ||
286 | subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG; | ||
287 | subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG; | ||
288 | } else { | ||
289 | subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; | ||
290 | subdevice->port_reg = reg_base + ME0900_PORT_B_REG; | ||
291 | subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG; | ||
292 | subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG; | ||
293 | } | ||
294 | #ifdef MEDEBUG_DEBUG_REG | ||
295 | subdevice->reg_base = reg_base; | ||
296 | #endif | ||
297 | |||
298 | /* Overload base class methods. */ | ||
299 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
300 | me0900_do_io_reset_subdevice; | ||
301 | subdevice->base.me_subdevice_io_single_config = | ||
302 | me0900_do_io_single_config; | ||
303 | subdevice->base.me_subdevice_io_single_read = me0900_do_io_single_read; | ||
304 | subdevice->base.me_subdevice_io_single_write = | ||
305 | me0900_do_io_single_write; | ||
306 | subdevice->base.me_subdevice_query_number_channels = | ||
307 | me0900_do_query_number_channels; | ||
308 | subdevice->base.me_subdevice_query_subdevice_type = | ||
309 | me0900_do_query_subdevice_type; | ||
310 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
311 | me0900_do_query_subdevice_caps; | ||
312 | |||
313 | return subdevice; | ||
314 | } | ||
diff --git a/drivers/staging/meilhaus/me0900_do.h b/drivers/staging/meilhaus/me0900_do.h deleted file mode 100644 index 13e8a8b94cfa..000000000000 --- a/drivers/staging/meilhaus/me0900_do.h +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0900_do.h | ||
3 | * | ||
4 | * @brief ME-9x digital output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0900_DO_H_ | ||
28 | #define _ME0900_DO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me0900_do_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | |||
44 | unsigned int do_idx; | ||
45 | |||
46 | unsigned long ctrl_reg; | ||
47 | unsigned long port_reg; | ||
48 | unsigned long enable_reg; | ||
49 | unsigned long disable_reg; | ||
50 | #ifdef MEDEBUG_DEBUG_REG | ||
51 | unsigned long reg_base; | ||
52 | #endif | ||
53 | } me0900_do_subdevice_t; | ||
54 | |||
55 | /** | ||
56 | * @brief The constructor to generate a ME-9x digital output subdevice instance. | ||
57 | * | ||
58 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
59 | * @param do_idx The index of the digital output subdevice on this device. | ||
60 | * | ||
61 | * @return Pointer to new instance on success.\n | ||
62 | * NULL on error. | ||
63 | */ | ||
64 | me0900_do_subdevice_t *me0900_do_constructor(uint32_t reg_base, | ||
65 | unsigned int do_idx); | ||
66 | |||
67 | #endif | ||
68 | #endif | ||
diff --git a/drivers/staging/meilhaus/me0900_reg.h b/drivers/staging/meilhaus/me0900_reg.h deleted file mode 100644 index 3bf163b6ac49..000000000000 --- a/drivers/staging/meilhaus/me0900_reg.h +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /** | ||
2 | * @file me0900_reg.h | ||
3 | * | ||
4 | * @brief ME-9x register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME0900_REG_H_ | ||
28 | #define _ME0900_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME0900_PORT_A_REG 0x00 | ||
33 | #define ME0900_PORT_B_REG 0x01 | ||
34 | #define ME0900_PORT_C_REG 0x02 | ||
35 | #define ME0900_CTRL_REG 0x03 // ( ,w) | ||
36 | #define ME0900_WRITE_ENABLE_REG 0x04 // (r,w) | ||
37 | #define ME0900_WRITE_DISABLE_REG 0x08 // (r,w) | ||
38 | |||
39 | #endif | ||
40 | #endif | ||
diff --git a/drivers/staging/meilhaus/me1000_device.c b/drivers/staging/meilhaus/me1000_device.c deleted file mode 100644 index cf0fb92f24c6..000000000000 --- a/drivers/staging/meilhaus/me1000_device.c +++ /dev/null | |||
@@ -1,206 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1000_device.c | ||
3 | * | ||
4 | * @brief ME-1000 device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include "meids.h" | ||
42 | #include "meerror.h" | ||
43 | #include "mecommon.h" | ||
44 | #include "meinternal.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "medevice.h" | ||
48 | #include "me1000_device.h" | ||
49 | #include "mesubdevice.h" | ||
50 | #include "me1000_dio.h" | ||
51 | |||
52 | static int me1000_config_load(me_device_t *me_device, struct file *filep, | ||
53 | me_cfg_device_entry_t *config) | ||
54 | { | ||
55 | me1000_device_t *me1000_device; | ||
56 | me1000_dio_subdevice_t *dio; | ||
57 | |||
58 | PDEBUG("executed.\n"); | ||
59 | |||
60 | me1000_device = (me1000_device_t *) me_device; | ||
61 | |||
62 | if (config->count == 2) { | ||
63 | if (me_slist_get_number_subdevices(&me1000_device->base.slist) | ||
64 | == 2) { | ||
65 | // Nothing to do. | ||
66 | } else { | ||
67 | // Remove 2 extra subdevices | ||
68 | dio = | ||
69 | (me1000_dio_subdevice_t *) | ||
70 | me_slist_del_subdevice_tail(&me1000_device->base. | ||
71 | slist); | ||
72 | if (dio) | ||
73 | dio->base. | ||
74 | me_subdevice_destructor((me_subdevice_t *) | ||
75 | dio); | ||
76 | |||
77 | dio = | ||
78 | (me1000_dio_subdevice_t *) | ||
79 | me_slist_del_subdevice_tail(&me1000_device->base. | ||
80 | slist); | ||
81 | if (dio) | ||
82 | dio->base. | ||
83 | me_subdevice_destructor((me_subdevice_t *) | ||
84 | dio); | ||
85 | } | ||
86 | } else if (config->count == 4) { | ||
87 | //Add 2 subdevices | ||
88 | if (me_slist_get_number_subdevices(&me1000_device->base.slist) | ||
89 | == 2) { | ||
90 | dio = | ||
91 | me1000_dio_constructor(me1000_device->base.info.pci. | ||
92 | reg_bases[2], 2, | ||
93 | &me1000_device->ctrl_lock); | ||
94 | if (!dio) { | ||
95 | PERROR("Cannot create dio subdevice.\n"); | ||
96 | return ME_ERRNO_INTERNAL; | ||
97 | } | ||
98 | me_slist_add_subdevice_tail(&me1000_device->base.slist, | ||
99 | (me_subdevice_t *) dio); | ||
100 | |||
101 | dio = | ||
102 | me1000_dio_constructor(me1000_device->base.info.pci. | ||
103 | reg_bases[2], 3, | ||
104 | &me1000_device->ctrl_lock); | ||
105 | if (!dio) { | ||
106 | dio = | ||
107 | (me1000_dio_subdevice_t *) | ||
108 | me_slist_del_subdevice_tail(&me1000_device-> | ||
109 | base.slist); | ||
110 | if (dio) | ||
111 | dio->base. | ||
112 | me_subdevice_destructor((me_subdevice_t *) dio); | ||
113 | |||
114 | PERROR("Cannot create dio subdevice.\n"); | ||
115 | return ME_ERRNO_INTERNAL; | ||
116 | } | ||
117 | me_slist_add_subdevice_tail(&me1000_device->base.slist, | ||
118 | (me_subdevice_t *) dio); | ||
119 | } else { | ||
120 | // Nothing to do. | ||
121 | } | ||
122 | } else { | ||
123 | PERROR("Invalid configuration.\n"); | ||
124 | return ME_ERRNO_INTERNAL; | ||
125 | } | ||
126 | |||
127 | return ME_ERRNO_SUCCESS; | ||
128 | } | ||
129 | |||
130 | me_device_t *me1000_pci_constructor(struct pci_dev * pci_device) | ||
131 | { | ||
132 | me1000_device_t *me1000_device; | ||
133 | me_subdevice_t *subdevice; | ||
134 | int err; | ||
135 | int i; | ||
136 | |||
137 | PDEBUG("executed.\n"); | ||
138 | |||
139 | // Allocate structure for device instance. | ||
140 | me1000_device = kmalloc(sizeof(me1000_device_t), GFP_KERNEL); | ||
141 | |||
142 | if (!me1000_device) { | ||
143 | PERROR("Cannot get memory for ME-1000 device instance.\n"); | ||
144 | return NULL; | ||
145 | } | ||
146 | |||
147 | memset(me1000_device, 0, sizeof(me1000_device_t)); | ||
148 | |||
149 | // Initialize base class structure. | ||
150 | err = me_device_pci_init((me_device_t *) me1000_device, pci_device); | ||
151 | |||
152 | if (err) { | ||
153 | kfree(me1000_device); | ||
154 | PERROR("Cannot initialize device base class.\n"); | ||
155 | return NULL; | ||
156 | } | ||
157 | // Initialize spin lock . | ||
158 | spin_lock_init(&me1000_device->ctrl_lock); | ||
159 | |||
160 | for (i = 0; i < 4; i++) { | ||
161 | subdevice = | ||
162 | (me_subdevice_t *) me1000_dio_constructor(me1000_device-> | ||
163 | base.info.pci. | ||
164 | reg_bases[2], i, | ||
165 | &me1000_device-> | ||
166 | ctrl_lock); | ||
167 | |||
168 | if (!subdevice) { | ||
169 | me_device_deinit((me_device_t *) me1000_device); | ||
170 | kfree(me1000_device); | ||
171 | PERROR("Cannot get memory for subdevice.\n"); | ||
172 | return NULL; | ||
173 | } | ||
174 | |||
175 | me_slist_add_subdevice_tail(&me1000_device->base.slist, | ||
176 | subdevice); | ||
177 | } | ||
178 | |||
179 | // Overwrite base class methods. | ||
180 | me1000_device->base.me_device_config_load = me1000_config_load; | ||
181 | |||
182 | return (me_device_t *) me1000_device; | ||
183 | } | ||
184 | EXPORT_SYMBOL(me1000_pci_constructor); | ||
185 | |||
186 | // Init and exit of module. | ||
187 | static int __init me1000_init(void) | ||
188 | { | ||
189 | PDEBUG("executed.\n"); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static void __exit me1000_exit(void) | ||
194 | { | ||
195 | PDEBUG("executed.\n"); | ||
196 | } | ||
197 | |||
198 | module_init(me1000_init); | ||
199 | module_exit(me1000_exit); | ||
200 | |||
201 | // Administrative stuff for modinfo. | ||
202 | MODULE_AUTHOR | ||
203 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
204 | MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-1000 Devices"); | ||
205 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-1000 Digital I/O Devices"); | ||
206 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me1000_device.h b/drivers/staging/meilhaus/me1000_device.h deleted file mode 100644 index cbbe1263017d..000000000000 --- a/drivers/staging/meilhaus/me1000_device.h +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1000_device.h | ||
3 | * | ||
4 | * @brief ME-1000 device class instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME1000_H_ | ||
28 | #define _ME1000_H_ | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | #define ME1000_MAGIC_NUMBER 1000 | ||
38 | |||
39 | /** | ||
40 | * @brief The ME-1000 device class structure. | ||
41 | */ | ||
42 | typedef struct me1000_device { | ||
43 | me_device_t base; /**< The Meilhaus device base class. */ | ||
44 | spinlock_t ctrl_lock; /**< Guards the DIO mode register. */ | ||
45 | } me1000_device_t; | ||
46 | |||
47 | /** | ||
48 | * @brief The ME-1000 device class constructor. | ||
49 | * | ||
50 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
51 | * | ||
52 | * @return On succes a new ME-1000 device instance. \n | ||
53 | * NULL on error. | ||
54 | */ | ||
55 | me_device_t *me1000_pci_constructor(struct pci_dev *pci_device) | ||
56 | __attribute__ ((weak)); | ||
57 | |||
58 | #endif | ||
59 | #endif | ||
diff --git a/drivers/staging/meilhaus/me1000_dio.c b/drivers/staging/meilhaus/me1000_dio.c deleted file mode 100644 index 2d7ed07d1f39..000000000000 --- a/drivers/staging/meilhaus/me1000_dio.c +++ /dev/null | |||
@@ -1,438 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1000_dio.c | ||
3 | * | ||
4 | * @brief ME-1000 DIO subdevice instance. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | #include "medebug.h" | ||
46 | |||
47 | #include "me1000_dio_reg.h" | ||
48 | #include "me1000_dio.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | #define ME1000_DIO_MAGIC_NUMBER 0x1000 /**< The magic number of the class structure. */ | ||
54 | |||
55 | /* | ||
56 | * Functions | ||
57 | */ | ||
58 | |||
59 | static int me1000_dio_io_reset_subdevice(struct me_subdevice *subdevice, | ||
60 | struct file *filep, int flags) | ||
61 | { | ||
62 | me1000_dio_subdevice_t *instance; | ||
63 | uint32_t tmp; | ||
64 | |||
65 | PDEBUG("executed.\n"); | ||
66 | |||
67 | instance = (me1000_dio_subdevice_t *) subdevice; | ||
68 | |||
69 | if (flags) { | ||
70 | PERROR("Invalid flag specified.\n"); | ||
71 | return ME_ERRNO_INVALID_FLAGS; | ||
72 | } | ||
73 | |||
74 | ME_SUBDEVICE_ENTER; | ||
75 | |||
76 | spin_lock(&instance->subdevice_lock); | ||
77 | spin_lock(instance->ctrl_reg_lock); | ||
78 | tmp = inl(instance->ctrl_reg); | ||
79 | tmp &= ~(0x1 << instance->dio_idx); | ||
80 | outl(tmp, instance->ctrl_reg); | ||
81 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
82 | instance->ctrl_reg - instance->reg_base, tmp); | ||
83 | spin_unlock(instance->ctrl_reg_lock); | ||
84 | |||
85 | outl(0x00000000, instance->port_reg); | ||
86 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
87 | instance->ctrl_reg - instance->reg_base, 0); | ||
88 | spin_unlock(&instance->subdevice_lock); | ||
89 | |||
90 | ME_SUBDEVICE_EXIT; | ||
91 | |||
92 | return ME_ERRNO_SUCCESS; | ||
93 | } | ||
94 | |||
95 | static int me1000_dio_io_single_config(struct me_subdevice *subdevice, | ||
96 | struct file *filep, | ||
97 | int channel, | ||
98 | int single_config, | ||
99 | int ref, | ||
100 | int trig_chan, | ||
101 | int trig_type, int trig_edge, int flags) | ||
102 | { | ||
103 | me1000_dio_subdevice_t *instance; | ||
104 | int err = ME_ERRNO_SUCCESS; | ||
105 | int ctrl; | ||
106 | int size = | ||
107 | flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE | ||
108 | | ME_IO_SINGLE_CONFIG_DIO_WORD | | ||
109 | ME_IO_SINGLE_CONFIG_DIO_DWORD); | ||
110 | |||
111 | PDEBUG("executed.\n"); | ||
112 | |||
113 | instance = (me1000_dio_subdevice_t *) subdevice; | ||
114 | |||
115 | ME_SUBDEVICE_ENTER; | ||
116 | |||
117 | spin_lock(&instance->subdevice_lock); | ||
118 | spin_lock(instance->ctrl_reg_lock); | ||
119 | ctrl = inl(instance->ctrl_reg); | ||
120 | |||
121 | switch (size) { | ||
122 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
123 | case ME_IO_SINGLE_CONFIG_DIO_DWORD: | ||
124 | if (channel == 0) { | ||
125 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
126 | ctrl &= ~(0x1 << instance->dio_idx); | ||
127 | } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
128 | ctrl |= 0x1 << instance->dio_idx; | ||
129 | } else { | ||
130 | PERROR("Invalid port direction.\n"); | ||
131 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
132 | } | ||
133 | } else { | ||
134 | PERROR("Invalid channel number.\n"); | ||
135 | err = ME_ERRNO_INVALID_CHANNEL; | ||
136 | } | ||
137 | break; | ||
138 | |||
139 | default: | ||
140 | PERROR("Invalid flags.\n"); | ||
141 | err = ME_ERRNO_INVALID_FLAGS; | ||
142 | } | ||
143 | |||
144 | if (!err) { | ||
145 | outl(ctrl, instance->ctrl_reg); | ||
146 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
147 | instance->reg_base, | ||
148 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
149 | } | ||
150 | spin_unlock(instance->ctrl_reg_lock); | ||
151 | spin_unlock(&instance->subdevice_lock); | ||
152 | |||
153 | ME_SUBDEVICE_EXIT; | ||
154 | |||
155 | return err; | ||
156 | } | ||
157 | |||
158 | static int me1000_dio_io_single_read(struct me_subdevice *subdevice, | ||
159 | struct file *filep, | ||
160 | int channel, | ||
161 | int *value, int time_out, int flags) | ||
162 | { | ||
163 | me1000_dio_subdevice_t *instance; | ||
164 | int err = ME_ERRNO_SUCCESS; | ||
165 | |||
166 | PDEBUG("executed.\n"); | ||
167 | |||
168 | instance = (me1000_dio_subdevice_t *) subdevice; | ||
169 | |||
170 | ME_SUBDEVICE_ENTER; | ||
171 | |||
172 | spin_lock(&instance->subdevice_lock); | ||
173 | switch (flags) { | ||
174 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
175 | if ((channel >= 0) && (channel < 32)) { | ||
176 | *value = inl(instance->port_reg) & (0x1 << channel); | ||
177 | } else { | ||
178 | PERROR("Invalid bit number.\n"); | ||
179 | err = ME_ERRNO_INVALID_CHANNEL; | ||
180 | } | ||
181 | break; | ||
182 | |||
183 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
184 | if ((channel >= 0) && (channel < 4)) { | ||
185 | *value = | ||
186 | (inl(instance->port_reg) >> (channel * 8)) & 0xFF; | ||
187 | } else { | ||
188 | PERROR("Invalid byte number.\n"); | ||
189 | err = ME_ERRNO_INVALID_CHANNEL; | ||
190 | } | ||
191 | break; | ||
192 | |||
193 | case ME_IO_SINGLE_TYPE_DIO_WORD: | ||
194 | if ((channel >= 0) && (channel < 2)) { | ||
195 | *value = | ||
196 | (inl(instance->port_reg) >> (channel * 16)) & | ||
197 | 0xFFFF; | ||
198 | } else { | ||
199 | PERROR("Invalid word number.\n"); | ||
200 | err = ME_ERRNO_INVALID_CHANNEL; | ||
201 | } | ||
202 | break; | ||
203 | |||
204 | case ME_IO_SINGLE_NO_FLAGS: | ||
205 | case ME_IO_SINGLE_TYPE_DIO_DWORD: | ||
206 | if (channel == 0) { | ||
207 | *value = inl(instance->port_reg); | ||
208 | } else { | ||
209 | PERROR("Invalid dword number.\n"); | ||
210 | err = ME_ERRNO_INVALID_CHANNEL; | ||
211 | } | ||
212 | break; | ||
213 | |||
214 | default: | ||
215 | PERROR("Invalid flags specified.\n"); | ||
216 | err = ME_ERRNO_INVALID_FLAGS; | ||
217 | } | ||
218 | spin_unlock(&instance->subdevice_lock); | ||
219 | |||
220 | ME_SUBDEVICE_EXIT; | ||
221 | |||
222 | return err; | ||
223 | } | ||
224 | |||
225 | static int me1000_dio_io_single_write(struct me_subdevice *subdevice, | ||
226 | struct file *filep, | ||
227 | int channel, | ||
228 | int value, int time_out, int flags) | ||
229 | { | ||
230 | me1000_dio_subdevice_t *instance; | ||
231 | int err = ME_ERRNO_SUCCESS; | ||
232 | uint32_t config; | ||
233 | uint32_t state; | ||
234 | |||
235 | PDEBUG("executed.\n"); | ||
236 | |||
237 | instance = (me1000_dio_subdevice_t *) subdevice; | ||
238 | |||
239 | ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); | ||
240 | spin_lock(instance->ctrl_reg_lock); | ||
241 | config = inl(instance->ctrl_reg) & (0x1 << instance->dio_idx); | ||
242 | switch (flags) { | ||
243 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
244 | if ((channel >= 0) && (channel < 32)) { | ||
245 | if (config) { | ||
246 | state = inl(instance->port_reg); | ||
247 | state = | ||
248 | value ? (state | (0x1 << channel)) : (state | ||
249 | & | ||
250 | ~(0x1 | ||
251 | << | ||
252 | channel)); | ||
253 | outl(state, instance->port_reg); | ||
254 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
255 | instance->reg_base, | ||
256 | instance->port_reg - | ||
257 | instance->reg_base, state); | ||
258 | } else { | ||
259 | PERROR("Port is not in output mode.\n"); | ||
260 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
261 | } | ||
262 | } else { | ||
263 | PERROR("Invalid bit number.\n"); | ||
264 | err = ME_ERRNO_INVALID_CHANNEL; | ||
265 | } | ||
266 | break; | ||
267 | |||
268 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
269 | if ((channel >= 0) && (channel < 4)) { | ||
270 | if (config) { | ||
271 | state = inl(instance->port_reg); | ||
272 | state &= ~(0xFF << (channel * 8)); | ||
273 | state |= (value & 0xFF) << (channel * 8); | ||
274 | outl(state, instance->port_reg); | ||
275 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
276 | instance->reg_base, | ||
277 | instance->port_reg - | ||
278 | instance->reg_base, state); | ||
279 | } else { | ||
280 | PERROR("Port is not in output mode.\n"); | ||
281 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
282 | } | ||
283 | } else { | ||
284 | PERROR("Invalid byte number.\n"); | ||
285 | err = ME_ERRNO_INVALID_CHANNEL; | ||
286 | } | ||
287 | break; | ||
288 | |||
289 | case ME_IO_SINGLE_TYPE_DIO_WORD: | ||
290 | if ((channel >= 0) && (channel < 2)) { | ||
291 | if (config) { | ||
292 | state = inl(instance->port_reg); | ||
293 | state &= ~(0xFFFF << (channel * 16)); | ||
294 | state |= (value & 0xFFFF) << (channel * 16); | ||
295 | outl(state, instance->port_reg); | ||
296 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
297 | instance->reg_base, | ||
298 | instance->port_reg - | ||
299 | instance->reg_base, state); | ||
300 | } else { | ||
301 | PERROR("Port is not in output mode.\n"); | ||
302 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
303 | } | ||
304 | } else { | ||
305 | PERROR("Invalid word number.\n"); | ||
306 | err = ME_ERRNO_INVALID_CHANNEL; | ||
307 | } | ||
308 | break; | ||
309 | |||
310 | case ME_IO_SINGLE_NO_FLAGS: | ||
311 | case ME_IO_SINGLE_TYPE_DIO_DWORD: | ||
312 | if (channel == 0) { | ||
313 | if (config) { | ||
314 | outl(value, instance->port_reg); | ||
315 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
316 | instance->reg_base, | ||
317 | instance->port_reg - | ||
318 | instance->reg_base, value); | ||
319 | } else { | ||
320 | PERROR("Port is not in output mode.\n"); | ||
321 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
322 | } | ||
323 | } else { | ||
324 | PERROR("Invalid dword number.\n"); | ||
325 | err = ME_ERRNO_INVALID_CHANNEL; | ||
326 | } | ||
327 | break; | ||
328 | |||
329 | default: | ||
330 | PERROR("Invalid flags specified.\n"); | ||
331 | err = ME_ERRNO_INVALID_FLAGS; | ||
332 | } | ||
333 | spin_unlock(instance->ctrl_reg_lock); | ||
334 | spin_unlock(&instance->subdevice_lock); | ||
335 | |||
336 | ME_SUBDEVICE_EXIT; | ||
337 | |||
338 | return err; | ||
339 | } | ||
340 | |||
341 | static int me1000_dio_query_number_channels(struct me_subdevice *subdevice, | ||
342 | int *number) | ||
343 | { | ||
344 | PDEBUG("executed.\n"); | ||
345 | *number = ME1000_DIO_NUMBER_CHANNELS; | ||
346 | return ME_ERRNO_SUCCESS; | ||
347 | } | ||
348 | |||
349 | static int me1000_dio_query_subdevice_type(struct me_subdevice *subdevice, | ||
350 | int *type, int *subtype) | ||
351 | { | ||
352 | PDEBUG("executed.\n"); | ||
353 | *type = ME_TYPE_DIO; | ||
354 | *subtype = ME_SUBTYPE_SINGLE; | ||
355 | return ME_ERRNO_SUCCESS; | ||
356 | } | ||
357 | |||
358 | static int me1000_dio_query_subdevice_caps(struct me_subdevice *subdevice, | ||
359 | int *caps) | ||
360 | { | ||
361 | me1000_dio_subdevice_t *instance; | ||
362 | |||
363 | PDEBUG("executed.\n"); | ||
364 | |||
365 | instance = (me1000_dio_subdevice_t *) subdevice; | ||
366 | |||
367 | *caps = ME_CAPS_DIO_DIR_DWORD; | ||
368 | |||
369 | return ME_ERRNO_SUCCESS; | ||
370 | } | ||
371 | |||
372 | me1000_dio_subdevice_t *me1000_dio_constructor(uint32_t reg_base, | ||
373 | unsigned int dio_idx, | ||
374 | spinlock_t *ctrl_reg_lock) | ||
375 | { | ||
376 | me1000_dio_subdevice_t *subdevice; | ||
377 | int err; | ||
378 | |||
379 | PDEBUG("executed.\n"); | ||
380 | |||
381 | /* Allocate memory for subdevice instance */ | ||
382 | subdevice = kmalloc(sizeof(me1000_dio_subdevice_t), GFP_KERNEL); | ||
383 | |||
384 | if (!subdevice) { | ||
385 | PERROR("Cannot get memory for ME-1000 DIO instance.\n"); | ||
386 | return NULL; | ||
387 | } | ||
388 | |||
389 | memset(subdevice, 0, sizeof(me1000_dio_subdevice_t)); | ||
390 | |||
391 | /* Check if counter index is out of range */ | ||
392 | |||
393 | if (dio_idx >= ME1000_DIO_NUMBER_PORTS) { | ||
394 | PERROR("DIO index is out of range.\n"); | ||
395 | kfree(subdevice); | ||
396 | return NULL; | ||
397 | } | ||
398 | |||
399 | /* Initialize subdevice base class */ | ||
400 | err = me_subdevice_init(&subdevice->base); | ||
401 | |||
402 | if (err) { | ||
403 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
404 | kfree(subdevice); | ||
405 | return NULL; | ||
406 | } | ||
407 | // Initialize spin locks. | ||
408 | spin_lock_init(&subdevice->subdevice_lock); | ||
409 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
410 | |||
411 | /* Save the DIO index */ | ||
412 | subdevice->dio_idx = dio_idx; | ||
413 | |||
414 | /* Initialize registers. */ | ||
415 | #ifdef MEDEBUG_DEBUG_REG | ||
416 | subdevice->reg_base = reg_base; | ||
417 | #endif | ||
418 | subdevice->ctrl_reg = reg_base + ME1000_PORT_MODE; | ||
419 | subdevice->port_reg = | ||
420 | reg_base + ME1000_PORT + (dio_idx * ME1000_PORT_STEP); | ||
421 | |||
422 | /* Override base class methods. */ | ||
423 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
424 | me1000_dio_io_reset_subdevice; | ||
425 | subdevice->base.me_subdevice_io_single_config = | ||
426 | me1000_dio_io_single_config; | ||
427 | subdevice->base.me_subdevice_io_single_read = me1000_dio_io_single_read; | ||
428 | subdevice->base.me_subdevice_io_single_write = | ||
429 | me1000_dio_io_single_write; | ||
430 | subdevice->base.me_subdevice_query_number_channels = | ||
431 | me1000_dio_query_number_channels; | ||
432 | subdevice->base.me_subdevice_query_subdevice_type = | ||
433 | me1000_dio_query_subdevice_type; | ||
434 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
435 | me1000_dio_query_subdevice_caps; | ||
436 | |||
437 | return subdevice; | ||
438 | } | ||
diff --git a/drivers/staging/meilhaus/me1000_dio.h b/drivers/staging/meilhaus/me1000_dio.h deleted file mode 100644 index d26e93f531af..000000000000 --- a/drivers/staging/meilhaus/me1000_dio.h +++ /dev/null | |||
@@ -1,71 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1000_dio.h | ||
3 | * | ||
4 | * @brief Meilhaus ME-1000 digital i/o implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME1000_DIO_H_ | ||
28 | #define _ME1000_DIO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | #include "meslock.h" | ||
32 | |||
33 | #ifdef __KERNEL__ | ||
34 | |||
35 | /** | ||
36 | * @brief The ME-1000 DIO subdevice class. | ||
37 | */ | ||
38 | typedef struct me1000_dio_subdevice { | ||
39 | /* Inheritance */ | ||
40 | me_subdevice_t base; /**< The subdevice base class. */ | ||
41 | |||
42 | /* Attributes */ | ||
43 | // uint32_t magic; /**< The magic number unique for this structure. */ | ||
44 | |||
45 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
46 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg and #ctrl_reg_mirror from concurrent access. */ | ||
47 | int dio_idx; /**< The index of the DIO port on the device. */ | ||
48 | |||
49 | unsigned long port_reg; /**< Register to read or write a value from or to the port respectively. */ | ||
50 | unsigned long ctrl_reg; /**< Register to configure the DIO modes. */ | ||
51 | #ifdef MEDEBUG_DEBUG_REG | ||
52 | unsigned long reg_base; | ||
53 | #endif | ||
54 | } me1000_dio_subdevice_t; | ||
55 | |||
56 | /** | ||
57 | * @brief The constructor to generate a ME-1000 DIO instance. | ||
58 | * | ||
59 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
60 | * @param dio_idx The index of the DIO on the device. | ||
61 | * @param ctrl_reg_lock Pointer to spin lock protecting the control register and from concurrent access. | ||
62 | * | ||
63 | * @return Pointer to new instance on success.\n | ||
64 | * NULL on error. | ||
65 | */ | ||
66 | me1000_dio_subdevice_t *me1000_dio_constructor(uint32_t reg_base, | ||
67 | unsigned int dio_idx, | ||
68 | spinlock_t * ctrl_reg_lock); | ||
69 | |||
70 | #endif | ||
71 | #endif | ||
diff --git a/drivers/staging/meilhaus/me1000_dio_reg.h b/drivers/staging/meilhaus/me1000_dio_reg.h deleted file mode 100644 index 4d5b38df437f..000000000000 --- a/drivers/staging/meilhaus/me1000_dio_reg.h +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1000_dio_reg.h | ||
3 | * | ||
4 | * @brief ME-1000 digital i/o register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef _ME1000_DIO_REG_H_ | ||
29 | # define _ME1000_DIO_REG_H_ | ||
30 | |||
31 | # ifdef __KERNEL__ | ||
32 | |||
33 | # define ME1000_DIO_NUMBER_CHANNELS 32 /**< The number of channels per DIO port. */ | ||
34 | # define ME1000_DIO_NUMBER_PORTS 4 /**< The number of ports per ME-1000. */ | ||
35 | |||
36 | // # define ME1000_PORT_A 0x0000 /**< Port A base register offset. */ | ||
37 | // # define ME1000_PORT_B 0x0004 /**< Port B base register offset. */ | ||
38 | // # define ME1000_PORT_C 0x0008 /**< Port C base register offset. */ | ||
39 | // # define ME1000_PORT_D 0x000C /**< Port D base register offset. */ | ||
40 | # define ME1000_PORT 0x0000 /**< Base for port's register. */ | ||
41 | # define ME1000_PORT_STEP 4 /**< Distance between port's register. */ | ||
42 | |||
43 | # define ME1000_PORT_MODE 0x0010 /**< Configuration register to switch the port direction. */ | ||
44 | // # define ME1000_PORT_MODE_OUTPUT_A (1 << 0) /**< If set, port A is in output, otherwise in input mode. */ | ||
45 | // # define ME1000_PORT_MODE_OUTPUT_B (1 << 1) /**< If set, port B is in output, otherwise in input mode. */ | ||
46 | // # define ME1000_PORT_MODE_OUTPUT_C (1 << 2) /**< If set, port C is in output, otherwise in input mode. */ | ||
47 | // # define ME1000_PORT_MODE_OUTPUT_D (1 << 3) /**< If set, port D is in output, otherwise in input mode. */ | ||
48 | |||
49 | # endif //__KERNEL__ | ||
50 | #endif //_ME1000_DIO_REG_H_ | ||
diff --git a/drivers/staging/meilhaus/me1400_device.c b/drivers/staging/meilhaus/me1400_device.c deleted file mode 100644 index a018b5f7a19b..000000000000 --- a/drivers/staging/meilhaus/me1400_device.c +++ /dev/null | |||
@@ -1,253 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1400_device.c | ||
3 | * | ||
4 | * @brief ME-1400 device instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | * User application could also include the kernel header files. But the | ||
30 | * real kernel functions are protected by #ifdef __KERNEL__. | ||
31 | */ | ||
32 | #ifndef __KERNEL__ | ||
33 | # define __KERNEL__ | ||
34 | #endif | ||
35 | |||
36 | /* | ||
37 | * This must be defined before module.h is included. Not needed, when | ||
38 | * it is a built in driver. | ||
39 | */ | ||
40 | #ifndef MODULE | ||
41 | # define MODULE | ||
42 | #endif | ||
43 | |||
44 | #include <linux/module.h> | ||
45 | |||
46 | #include <linux/pci.h> | ||
47 | #include <linux/slab.h> | ||
48 | #include <linux/sched.h> | ||
49 | #include <linux/interrupt.h> | ||
50 | |||
51 | #include "meids.h" | ||
52 | #include "meerror.h" | ||
53 | #include "mecommon.h" | ||
54 | #include "meinternal.h" | ||
55 | |||
56 | #include "medebug.h" | ||
57 | |||
58 | #include "me1400_device.h" | ||
59 | #include "me8254.h" | ||
60 | #include "me8254_reg.h" | ||
61 | #include "me8255.h" | ||
62 | #include "me1400_ext_irq.h" | ||
63 | |||
64 | me_device_t *me1400_pci_constructor(struct pci_dev *pci_device) | ||
65 | { | ||
66 | int err; | ||
67 | me1400_device_t *me1400_device; | ||
68 | me_subdevice_t *subdevice; | ||
69 | unsigned int version_idx; | ||
70 | unsigned int me8255_idx; | ||
71 | unsigned int dio_idx; | ||
72 | unsigned int me8254_idx; | ||
73 | unsigned int ctr_idx; | ||
74 | unsigned int ext_irq_idx; | ||
75 | |||
76 | PDEBUG("executed.\n"); | ||
77 | |||
78 | // Allocate structure for device instance. | ||
79 | me1400_device = kmalloc(sizeof(me1400_device_t), GFP_KERNEL); | ||
80 | |||
81 | if (!me1400_device) { | ||
82 | PERROR("Cannot get memory for 1400ate device instance.\n"); | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | memset(me1400_device, 0, sizeof(me1400_device_t)); | ||
87 | |||
88 | // Initialize base class structure. | ||
89 | err = me_device_pci_init((me_device_t *) me1400_device, pci_device); | ||
90 | |||
91 | if (err) { | ||
92 | kfree(me1400_device); | ||
93 | PERROR("Cannot initialize device base class.\n"); | ||
94 | return NULL; | ||
95 | } | ||
96 | |||
97 | /* Check for ME1400 extension device. If detected we fake a ME-1400 D device id. */ | ||
98 | if (me1400_device->base.info.pci.device_id == | ||
99 | PCI_DEVICE_ID_MEILHAUS_ME140C) { | ||
100 | uint8_t ctrl; | ||
101 | ctrl = | ||
102 | inb(me1400_device->base.info.pci.reg_bases[2] + | ||
103 | ME1400D_CLK_SRC_2_REG); | ||
104 | PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n", | ||
105 | me1400_device->base.info.pci.reg_bases[2], | ||
106 | ME1400D_CLK_SRC_2_REG, ctrl); | ||
107 | outb(ctrl | 0xF0, | ||
108 | me1400_device->base.info.pci.reg_bases[2] + | ||
109 | ME1400D_CLK_SRC_2_REG); | ||
110 | PDEBUG_REG("xxx_reg outb(0x%X+0x%X)=0x%x\n", | ||
111 | me1400_device->base.info.pci.reg_bases[2], | ||
112 | ME1400D_CLK_SRC_2_REG, ctrl | 0xF0); | ||
113 | ctrl = | ||
114 | inb(me1400_device->base.info.pci.reg_bases[2] + | ||
115 | ME1400D_CLK_SRC_2_REG); | ||
116 | PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n", | ||
117 | me1400_device->base.info.pci.reg_bases[2], | ||
118 | ME1400D_CLK_SRC_2_REG, ctrl); | ||
119 | |||
120 | if ((ctrl & 0xF0) == 0xF0) { | ||
121 | PINFO("ME1400 D detected.\n"); | ||
122 | me1400_device->base.info.pci.device_id = | ||
123 | PCI_DEVICE_ID_MEILHAUS_ME140D; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | /* Initialize global stuff of digital i/o subdevices. */ | ||
128 | for (me8255_idx = 0; me8255_idx < ME1400_MAX_8255; me8255_idx++) { | ||
129 | me1400_device->dio_current_mode[me8255_idx] = 0; | ||
130 | spin_lock_init(&me1400_device->dio_ctrl_reg_lock[me8255_idx]); | ||
131 | } | ||
132 | |||
133 | /* Initialize global stuff of counter subdevices. */ | ||
134 | spin_lock_init(&me1400_device->clk_src_reg_lock); | ||
135 | |||
136 | for (me8254_idx = 0; me8254_idx < ME1400_MAX_8254; me8254_idx++) | ||
137 | spin_lock_init(&me1400_device->ctr_ctrl_reg_lock[me8254_idx]); | ||
138 | |||
139 | /* Get the index in the device version information table. */ | ||
140 | version_idx = | ||
141 | me1400_versions_get_device_index(me1400_device->base.info.pci. | ||
142 | device_id); | ||
143 | |||
144 | /* Generate DIO subdevice instances. */ | ||
145 | for (me8255_idx = 0; | ||
146 | me8255_idx < me1400_versions[version_idx].dio_chips; | ||
147 | me8255_idx++) { | ||
148 | for (dio_idx = 0; dio_idx < 3; dio_idx++) { | ||
149 | subdevice = | ||
150 | (me_subdevice_t *) | ||
151 | me8255_constructor(me1400_versions[version_idx]. | ||
152 | device_id, | ||
153 | me1400_device->base.info.pci. | ||
154 | reg_bases[2], me8255_idx, | ||
155 | dio_idx, | ||
156 | &me1400_device-> | ||
157 | dio_current_mode[me8255_idx], | ||
158 | &me1400_device-> | ||
159 | dio_ctrl_reg_lock[me8255_idx]); | ||
160 | |||
161 | if (!subdevice) { | ||
162 | me_device_deinit((me_device_t *) me1400_device); | ||
163 | kfree(me1400_device); | ||
164 | PERROR("Cannot get memory for subdevice.\n"); | ||
165 | return NULL; | ||
166 | } | ||
167 | |||
168 | me_slist_add_subdevice_tail(&me1400_device->base.slist, | ||
169 | subdevice); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /* Generate counter subdevice instances. */ | ||
174 | for (me8254_idx = 0; | ||
175 | me8254_idx < me1400_versions[version_idx].ctr_chips; | ||
176 | me8254_idx++) { | ||
177 | for (ctr_idx = 0; ctr_idx < 3; ctr_idx++) { | ||
178 | subdevice = | ||
179 | (me_subdevice_t *) | ||
180 | me8254_constructor(me1400_device->base.info.pci. | ||
181 | device_id, | ||
182 | me1400_device->base.info.pci. | ||
183 | reg_bases[2], me8254_idx, | ||
184 | ctr_idx, | ||
185 | &me1400_device-> | ||
186 | ctr_ctrl_reg_lock[me8254_idx], | ||
187 | &me1400_device-> | ||
188 | clk_src_reg_lock); | ||
189 | |||
190 | if (!subdevice) { | ||
191 | me_device_deinit((me_device_t *) me1400_device); | ||
192 | kfree(me1400_device); | ||
193 | PERROR("Cannot get memory for subdevice.\n"); | ||
194 | return NULL; | ||
195 | } | ||
196 | |||
197 | me_slist_add_subdevice_tail(&me1400_device->base.slist, | ||
198 | subdevice); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /* Generate external interrupt subdevice instances. */ | ||
203 | for (ext_irq_idx = 0; | ||
204 | ext_irq_idx < me1400_versions[version_idx].ext_irq_subdevices; | ||
205 | ext_irq_idx++) { | ||
206 | subdevice = | ||
207 | (me_subdevice_t *) | ||
208 | me1400_ext_irq_constructor(me1400_device->base.info.pci. | ||
209 | device_id, | ||
210 | me1400_device->base.info.pci. | ||
211 | reg_bases[1], | ||
212 | me1400_device->base.info.pci. | ||
213 | reg_bases[2], | ||
214 | &me1400_device->clk_src_reg_lock, | ||
215 | me1400_device->base.irq); | ||
216 | |||
217 | if (!subdevice) { | ||
218 | me_device_deinit((me_device_t *) me1400_device); | ||
219 | kfree(me1400_device); | ||
220 | PERROR("Cannot get memory for subdevice.\n"); | ||
221 | return NULL; | ||
222 | } | ||
223 | |||
224 | me_slist_add_subdevice_tail(&me1400_device->base.slist, | ||
225 | subdevice); | ||
226 | } | ||
227 | |||
228 | return (me_device_t *) me1400_device; | ||
229 | } | ||
230 | EXPORT_SYMBOL(me1400_pci_constructor); | ||
231 | |||
232 | // Init and exit of module. | ||
233 | |||
234 | static int __init me1400_init(void) | ||
235 | { | ||
236 | PDEBUG("executed.\n"); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static void __exit me1400_exit(void) | ||
241 | { | ||
242 | PDEBUG("executed.\n"); | ||
243 | } | ||
244 | |||
245 | module_init(me1400_init); | ||
246 | module_exit(me1400_exit); | ||
247 | |||
248 | // Administrative stuff for modinfo. | ||
249 | MODULE_AUTHOR | ||
250 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
251 | MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-14xx devices"); | ||
252 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-14xx MIO devices"); | ||
253 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me1400_device.h b/drivers/staging/meilhaus/me1400_device.h deleted file mode 100644 index d20112d8da60..000000000000 --- a/drivers/staging/meilhaus/me1400_device.h +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1400_device.c | ||
3 | * | ||
4 | * @brief ME-1400 device family instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME1400_DEVICE_H_ | ||
28 | #define _ME1400_DEVICE_H_ | ||
29 | |||
30 | #include "metypes.h" | ||
31 | #include "medefines.h" | ||
32 | #include "meinternal.h" | ||
33 | |||
34 | #include "medevice.h" | ||
35 | |||
36 | #ifdef __KERNEL__ | ||
37 | |||
38 | /** | ||
39 | * @brief Structure to store device capabilities. | ||
40 | */ | ||
41 | typedef struct me1400_version { | ||
42 | uint16_t device_id; /**< The PCI device id of the device. */ | ||
43 | unsigned int dio_chips; /**< The number of 8255 chips on the device. */ | ||
44 | unsigned int ctr_chips; /**< The number of 8254 chips on the device. */ | ||
45 | unsigned int ext_irq_subdevices; /**< The number of external interrupt inputs on the device. */ | ||
46 | } me1400_version_t; | ||
47 | |||
48 | /** | ||
49 | * @brief Defines for each ME-1400 device version its capabilities. | ||
50 | */ | ||
51 | static me1400_version_t me1400_versions[] = { | ||
52 | {PCI_DEVICE_ID_MEILHAUS_ME1400, 1, 0, 0}, | ||
53 | {PCI_DEVICE_ID_MEILHAUS_ME140A, 1, 1, 1}, | ||
54 | {PCI_DEVICE_ID_MEILHAUS_ME140B, 2, 2, 1}, | ||
55 | {PCI_DEVICE_ID_MEILHAUS_ME14E0, 1, 0, 0}, | ||
56 | {PCI_DEVICE_ID_MEILHAUS_ME14EA, 1, 1, 1}, | ||
57 | {PCI_DEVICE_ID_MEILHAUS_ME14EB, 2, 2, 1}, | ||
58 | {PCI_DEVICE_ID_MEILHAUS_ME140C, 1, 5, 1}, | ||
59 | {PCI_DEVICE_ID_MEILHAUS_ME140D, 2, 10, 1}, | ||
60 | {0} | ||
61 | }; | ||
62 | |||
63 | #define ME1400_DEVICE_VERSIONS (ARRAY_SIZE(me1400_versions) - 1) /**< Returns the number of entries in #me1400_versions. */ | ||
64 | |||
65 | /** | ||
66 | * @brief Returns the index of the device entry in #me1400_versions. | ||
67 | * | ||
68 | * @param device_id The PCI device id of the device to query. | ||
69 | * @return The index of the device in #me1400_versions. | ||
70 | */ | ||
71 | static inline unsigned int me1400_versions_get_device_index(uint16_t device_id) | ||
72 | { | ||
73 | unsigned int i; | ||
74 | for (i = 0; i < ME1400_DEVICE_VERSIONS; i++) | ||
75 | if (me1400_versions[i].device_id == device_id) | ||
76 | break; | ||
77 | return i; | ||
78 | } | ||
79 | |||
80 | #define ME1400_MAX_8254 10 /**< The maximum number of 8254 counter subdevices available on any ME-1400 device. */ | ||
81 | #define ME1400_MAX_8255 2 /**< The maximum number of 8255 digital i/o subdevices available on any ME-1400 device. */ | ||
82 | |||
83 | /** | ||
84 | * @brief The ME-1400 device class. | ||
85 | */ | ||
86 | typedef struct me1400_device { | ||
87 | me_device_t base; /**< The Meilhaus device base class. */ | ||
88 | |||
89 | spinlock_t clk_src_reg_lock; /**< Guards the 8254 clock source registers. */ | ||
90 | spinlock_t ctr_ctrl_reg_lock[ME1400_MAX_8254]; /**< Guards the 8254 ctrl registers. */ | ||
91 | |||
92 | int dio_current_mode[ME1400_MAX_8255]; /**< Saves the current mode setting of a single 8255 DIO chip. */ | ||
93 | spinlock_t dio_ctrl_reg_lock[ME1400_MAX_8255]; /**< Guards the 8255 ctrl register and #dio_current_mode. */ | ||
94 | } me1400_device_t; | ||
95 | |||
96 | /** | ||
97 | * @brief The ME-1400 device class constructor. | ||
98 | * | ||
99 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
100 | * | ||
101 | * @return On succes a new ME-1400 device instance. \n | ||
102 | * NULL on error. | ||
103 | */ | ||
104 | me_device_t *me1400_pci_constructor(struct pci_dev *pci_device) | ||
105 | __attribute__ ((weak)); | ||
106 | |||
107 | #endif | ||
108 | #endif | ||
diff --git a/drivers/staging/meilhaus/me1400_ext_irq.c b/drivers/staging/meilhaus/me1400_ext_irq.c deleted file mode 100644 index 6841f41860a2..000000000000 --- a/drivers/staging/meilhaus/me1400_ext_irq.c +++ /dev/null | |||
@@ -1,507 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1400_ext_irq.c | ||
3 | * | ||
4 | * @brief ME-1400 external interrupt subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | |||
43 | #include "medefines.h" | ||
44 | #include "meinternal.h" | ||
45 | #include "meerror.h" | ||
46 | #include "medebug.h" | ||
47 | #include "meids.h" | ||
48 | |||
49 | #include "me1400_ext_irq.h" | ||
50 | #include "me1400_ext_irq_reg.h" | ||
51 | |||
52 | /* | ||
53 | * Defines | ||
54 | */ | ||
55 | #define ME1400_EXT_IRQ_MAGIC_NUMBER 0x1401 /**< The magic number of the class structure. */ | ||
56 | #define ME1400_EXT_IRQ_NUMBER_CHANNELS 1 /**< One channel per counter. */ | ||
57 | |||
58 | /* | ||
59 | * Functions | ||
60 | */ | ||
61 | |||
62 | static int me1400_ext_irq_io_irq_start(struct me_subdevice *subdevice, | ||
63 | struct file *filep, | ||
64 | int channel, | ||
65 | int irq_source, | ||
66 | int irq_edge, int irq_arg, int flags) | ||
67 | { | ||
68 | me1400_ext_irq_subdevice_t *instance; | ||
69 | unsigned long cpu_flags; | ||
70 | uint8_t tmp; | ||
71 | |||
72 | PDEBUG("executed.\n"); | ||
73 | |||
74 | instance = (me1400_ext_irq_subdevice_t *) subdevice; | ||
75 | |||
76 | if (flags & ~ME_IO_IRQ_START_DIO_BIT) { | ||
77 | PERROR("Invalid flag specified.\n"); | ||
78 | return ME_ERRNO_INVALID_FLAGS; | ||
79 | } | ||
80 | |||
81 | if (channel) { | ||
82 | PERROR("Invalid channel.\n"); | ||
83 | return ME_ERRNO_INVALID_CHANNEL; | ||
84 | } | ||
85 | |||
86 | if (irq_source != ME_IRQ_SOURCE_DIO_LINE) { | ||
87 | PERROR("Invalid irq source.\n"); | ||
88 | return ME_ERRNO_INVALID_IRQ_SOURCE; | ||
89 | } | ||
90 | |||
91 | if (irq_edge != ME_IRQ_EDGE_RISING) { | ||
92 | PERROR("Invalid irq edge.\n"); | ||
93 | return ME_ERRNO_INVALID_IRQ_EDGE; | ||
94 | } | ||
95 | |||
96 | ME_SUBDEVICE_ENTER; | ||
97 | |||
98 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
99 | |||
100 | spin_lock(instance->clk_src_reg_lock); | ||
101 | // // Enable IRQ on PLX | ||
102 | // tmp = inb(instance->plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN); | ||
103 | // outb(tmp, instance->plx_intcs_reg); | ||
104 | // PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp); | ||
105 | |||
106 | // Enable IRQ | ||
107 | switch (instance->device_id) { | ||
108 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
109 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
110 | tmp = inb(instance->ctrl_reg); | ||
111 | tmp |= ME1400CD_EXT_IRQ_CLK_EN; | ||
112 | outb(tmp, instance->ctrl_reg); | ||
113 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
114 | instance->reg_base, | ||
115 | instance->ctrl_reg - instance->reg_base, tmp); | ||
116 | break; | ||
117 | |||
118 | default: | ||
119 | outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg); | ||
120 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
121 | instance->reg_base, | ||
122 | instance->ctrl_reg - instance->reg_base, | ||
123 | ME1400AB_EXT_IRQ_IRQ_EN); | ||
124 | break; | ||
125 | } | ||
126 | spin_unlock(instance->clk_src_reg_lock); | ||
127 | instance->rised = 0; | ||
128 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
129 | |||
130 | ME_SUBDEVICE_EXIT; | ||
131 | |||
132 | return ME_ERRNO_SUCCESS; | ||
133 | } | ||
134 | |||
135 | static int me1400_ext_irq_io_irq_wait(struct me_subdevice *subdevice, | ||
136 | struct file *filep, | ||
137 | int channel, | ||
138 | int *irq_count, | ||
139 | int *value, int time_out, int flags) | ||
140 | { | ||
141 | me1400_ext_irq_subdevice_t *instance; | ||
142 | unsigned long cpu_flags; | ||
143 | long t = 0; | ||
144 | int err = ME_ERRNO_SUCCESS; | ||
145 | |||
146 | PDEBUG("executed.\n"); | ||
147 | |||
148 | instance = (me1400_ext_irq_subdevice_t *) subdevice; | ||
149 | |||
150 | if (flags) { | ||
151 | PERROR("Invalid flag specified.\n"); | ||
152 | return ME_ERRNO_INVALID_FLAGS; | ||
153 | } | ||
154 | |||
155 | if (channel) { | ||
156 | PERROR("Invalid channel.\n"); | ||
157 | return ME_ERRNO_INVALID_CHANNEL; | ||
158 | } | ||
159 | |||
160 | if (time_out < 0) { | ||
161 | PERROR("Invalid time out.\n"); | ||
162 | return ME_ERRNO_INVALID_TIMEOUT; | ||
163 | } | ||
164 | |||
165 | if (time_out) { | ||
166 | /* Convert to ticks */ | ||
167 | t = (time_out * HZ) / 1000; | ||
168 | |||
169 | if (t == 0) | ||
170 | t = 1; | ||
171 | } | ||
172 | |||
173 | ME_SUBDEVICE_ENTER; | ||
174 | |||
175 | if (instance->rised <= 0) { | ||
176 | instance->rised = 0; | ||
177 | if (time_out) { | ||
178 | t = wait_event_interruptible_timeout(instance-> | ||
179 | wait_queue, | ||
180 | (instance->rised != | ||
181 | 0), t); | ||
182 | |||
183 | if (t == 0) { | ||
184 | PERROR("Wait on interrupt timed out.\n"); | ||
185 | err = ME_ERRNO_TIMEOUT; | ||
186 | } | ||
187 | } else { | ||
188 | wait_event_interruptible(instance->wait_queue, | ||
189 | (instance->rised != 0)); | ||
190 | } | ||
191 | |||
192 | if (instance->rised < 0) { | ||
193 | PERROR("Wait on interrupt aborted by user.\n"); | ||
194 | err = ME_ERRNO_CANCELLED; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | if (signal_pending(current)) { | ||
199 | PERROR("Wait on interrupt aborted by signal.\n"); | ||
200 | err = ME_ERRNO_SIGNAL; | ||
201 | } | ||
202 | |||
203 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
204 | instance->rised = 0; | ||
205 | *irq_count = instance->n; | ||
206 | *value = 1; | ||
207 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
208 | |||
209 | ME_SUBDEVICE_EXIT; | ||
210 | |||
211 | return err; | ||
212 | } | ||
213 | |||
214 | static int me1400_ext_irq_io_irq_stop(struct me_subdevice *subdevice, | ||
215 | struct file *filep, | ||
216 | int channel, int flags) | ||
217 | { | ||
218 | me1400_ext_irq_subdevice_t *instance; | ||
219 | unsigned long cpu_flags; | ||
220 | uint8_t tmp; | ||
221 | int err = ME_ERRNO_SUCCESS; | ||
222 | |||
223 | PDEBUG("executed.\n"); | ||
224 | |||
225 | instance = (me1400_ext_irq_subdevice_t *) subdevice; | ||
226 | |||
227 | if (flags) { | ||
228 | PERROR("Invalid flag specified.\n"); | ||
229 | return ME_ERRNO_INVALID_FLAGS; | ||
230 | } | ||
231 | |||
232 | if (channel) { | ||
233 | PERROR("Invalid channel.\n"); | ||
234 | return ME_ERRNO_INVALID_CHANNEL; | ||
235 | } | ||
236 | |||
237 | ME_SUBDEVICE_ENTER; | ||
238 | |||
239 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
240 | spin_lock(instance->clk_src_reg_lock); | ||
241 | // // Disable IRQ on PLX | ||
242 | // tmp = inb(instance->plx_intcs_reg) & ( ~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN)); | ||
243 | // outb(tmp, instance->plx_intcs_reg); | ||
244 | // PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp); | ||
245 | |||
246 | switch (instance->device_id) { | ||
247 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
248 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
249 | tmp = inb(instance->ctrl_reg); | ||
250 | tmp &= ~ME1400CD_EXT_IRQ_CLK_EN; | ||
251 | outb(tmp, instance->ctrl_reg); | ||
252 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
253 | instance->reg_base, | ||
254 | instance->ctrl_reg - instance->reg_base, tmp); | ||
255 | |||
256 | break; | ||
257 | |||
258 | default: | ||
259 | outb(0x00, instance->ctrl_reg); | ||
260 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
261 | instance->reg_base, | ||
262 | instance->ctrl_reg - instance->reg_base, 0x00); | ||
263 | break; | ||
264 | } | ||
265 | spin_unlock(instance->clk_src_reg_lock); | ||
266 | instance->rised = -1; | ||
267 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
268 | wake_up_interruptible_all(&instance->wait_queue); | ||
269 | |||
270 | ME_SUBDEVICE_EXIT; | ||
271 | |||
272 | return err; | ||
273 | } | ||
274 | |||
275 | static int me1400_ext_irq_io_reset_subdevice(struct me_subdevice *subdevice, | ||
276 | struct file *filep, int flags) | ||
277 | { | ||
278 | me1400_ext_irq_subdevice_t *instance = | ||
279 | (me1400_ext_irq_subdevice_t *) subdevice; | ||
280 | |||
281 | PDEBUG("executed.\n"); | ||
282 | |||
283 | if (flags) { | ||
284 | PERROR("Invalid flag specified.\n"); | ||
285 | return ME_ERRNO_INVALID_FLAGS; | ||
286 | } | ||
287 | |||
288 | instance->n = 0; | ||
289 | return me1400_ext_irq_io_irq_stop(subdevice, filep, 0, flags); | ||
290 | } | ||
291 | |||
292 | static int me1400_ext_irq_query_number_channels(struct me_subdevice *subdevice, | ||
293 | int *number) | ||
294 | { | ||
295 | PDEBUG("executed.\n"); | ||
296 | *number = ME1400_EXT_IRQ_NUMBER_CHANNELS; | ||
297 | return ME_ERRNO_SUCCESS; | ||
298 | } | ||
299 | |||
300 | static int me1400_ext_irq_query_subdevice_type(struct me_subdevice *subdevice, | ||
301 | int *type, int *subtype) | ||
302 | { | ||
303 | PDEBUG("executed.\n"); | ||
304 | *type = ME_TYPE_EXT_IRQ; | ||
305 | *subtype = ME_SUBTYPE_SINGLE; | ||
306 | return ME_ERRNO_SUCCESS; | ||
307 | } | ||
308 | |||
309 | static int me1400_ext_irq_query_subdevice_caps(struct me_subdevice *subdevice, | ||
310 | int *caps) | ||
311 | { | ||
312 | PDEBUG("executed.\n"); | ||
313 | *caps = ME_CAPS_EXT_IRQ_EDGE_RISING; | ||
314 | return ME_ERRNO_SUCCESS; | ||
315 | } | ||
316 | |||
317 | static int me1400_ext_irq_query_subdevice_caps_args(struct me_subdevice | ||
318 | *subdevice, int cap, | ||
319 | int *args, int count) | ||
320 | { | ||
321 | PDEBUG("executed.\n"); | ||
322 | return ME_ERRNO_NOT_SUPPORTED; | ||
323 | } | ||
324 | |||
325 | static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id) | ||
326 | { | ||
327 | me1400_ext_irq_subdevice_t *instance; | ||
328 | uint32_t status; | ||
329 | uint8_t tmp; | ||
330 | |||
331 | instance = (me1400_ext_irq_subdevice_t *) dev_id; | ||
332 | |||
333 | if (irq != instance->irq) { | ||
334 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
335 | return IRQ_NONE; | ||
336 | } | ||
337 | |||
338 | spin_lock(&instance->subdevice_lock); | ||
339 | status = inl(instance->plx_intcs_reg); | ||
340 | // if (!((status & PLX_LOCAL_INT1_STATE) && (status & PLX_LOCAL_INT1_EN) && (status & PLX_PCI_INT_EN))) | ||
341 | if ((status & | ||
342 | (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) != | ||
343 | (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) { | ||
344 | spin_unlock(&instance->subdevice_lock); | ||
345 | PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n", | ||
346 | jiffies, __func__, status); | ||
347 | return IRQ_NONE; | ||
348 | } | ||
349 | |||
350 | inl(instance->ctrl_reg); | ||
351 | |||
352 | PDEBUG("executed.\n"); | ||
353 | |||
354 | instance->n++; | ||
355 | instance->rised = 1; | ||
356 | |||
357 | switch (instance->device_id) { | ||
358 | |||
359 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
360 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
361 | spin_lock(instance->clk_src_reg_lock); | ||
362 | tmp = inb(instance->ctrl_reg); | ||
363 | tmp &= ~ME1400CD_EXT_IRQ_CLK_EN; | ||
364 | outb(tmp, instance->ctrl_reg); | ||
365 | PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
366 | instance->reg_base, | ||
367 | instance->ctrl_reg - instance->reg_base, tmp); | ||
368 | tmp |= ME1400CD_EXT_IRQ_CLK_EN; | ||
369 | outb(tmp, instance->ctrl_reg); | ||
370 | PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
371 | instance->reg_base, | ||
372 | instance->ctrl_reg - instance->reg_base, tmp); | ||
373 | spin_unlock(instance->clk_src_reg_lock); | ||
374 | |||
375 | break; | ||
376 | |||
377 | default: | ||
378 | outb(0, instance->ctrl_reg); | ||
379 | PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
380 | instance->reg_base, | ||
381 | instance->ctrl_reg - instance->reg_base, 0); | ||
382 | outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg); | ||
383 | PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
384 | instance->reg_base, | ||
385 | instance->ctrl_reg - instance->reg_base, | ||
386 | ME1400AB_EXT_IRQ_IRQ_EN); | ||
387 | break; | ||
388 | } | ||
389 | |||
390 | spin_unlock(&instance->subdevice_lock); | ||
391 | wake_up_interruptible_all(&instance->wait_queue); | ||
392 | |||
393 | return IRQ_HANDLED; | ||
394 | } | ||
395 | |||
396 | static void me1400_ext_irq_destructor(struct me_subdevice *subdevice) | ||
397 | { | ||
398 | me1400_ext_irq_subdevice_t *instance; | ||
399 | uint8_t tmp; | ||
400 | |||
401 | PDEBUG("executed.\n"); | ||
402 | |||
403 | instance = (me1400_ext_irq_subdevice_t *) subdevice; | ||
404 | |||
405 | // Disable IRQ on PLX | ||
406 | tmp = | ||
407 | inb(instance-> | ||
408 | plx_intcs_reg) & (~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | | ||
409 | PLX_PCI_INT_EN)); | ||
410 | outb(tmp, instance->plx_intcs_reg); | ||
411 | PDEBUG_REG("ctrl_reg outb(plx:0x%lX)=0x%x\n", instance->plx_intcs_reg, | ||
412 | tmp); | ||
413 | |||
414 | free_irq(instance->irq, (void *)instance); | ||
415 | me_subdevice_deinit(&instance->base); | ||
416 | kfree(instance); | ||
417 | } | ||
418 | |||
419 | me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id, | ||
420 | uint32_t plx_reg_base, | ||
421 | uint32_t me1400_reg_base, | ||
422 | spinlock_t * | ||
423 | clk_src_reg_lock, | ||
424 | int irq) | ||
425 | { | ||
426 | me1400_ext_irq_subdevice_t *subdevice; | ||
427 | int err; | ||
428 | uint8_t tmp; | ||
429 | |||
430 | PDEBUG("executed.\n"); | ||
431 | |||
432 | /* Allocate memory for subdevice instance */ | ||
433 | subdevice = kmalloc(sizeof(me1400_ext_irq_subdevice_t), GFP_KERNEL); | ||
434 | |||
435 | if (!subdevice) { | ||
436 | PERROR("Cannot get memory for 1400_ext_irq instance.\n"); | ||
437 | return NULL; | ||
438 | } | ||
439 | |||
440 | memset(subdevice, 0, sizeof(me1400_ext_irq_subdevice_t)); | ||
441 | |||
442 | /* Initialize subdevice base class */ | ||
443 | err = me_subdevice_init(&subdevice->base); | ||
444 | |||
445 | if (err) { | ||
446 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
447 | kfree(subdevice); | ||
448 | return NULL; | ||
449 | } | ||
450 | // Initialize spin locks. | ||
451 | spin_lock_init(&subdevice->subdevice_lock); | ||
452 | subdevice->clk_src_reg_lock = clk_src_reg_lock; | ||
453 | |||
454 | /* Initialize wait queue */ | ||
455 | init_waitqueue_head(&subdevice->wait_queue); | ||
456 | |||
457 | subdevice->irq = irq; | ||
458 | |||
459 | err = request_irq(irq, me1400_ext_irq_isr, | ||
460 | IRQF_DISABLED | IRQF_SHARED, | ||
461 | ME1400_NAME, (void *)subdevice); | ||
462 | |||
463 | if (err) { | ||
464 | PERROR("Can't get irq.\n"); | ||
465 | me_subdevice_deinit(&subdevice->base); | ||
466 | kfree(subdevice); | ||
467 | return NULL; | ||
468 | } | ||
469 | PINFO("Registered irq=%d.\n", subdevice->irq); | ||
470 | |||
471 | /* Initialize registers */ | ||
472 | subdevice->plx_intcs_reg = plx_reg_base + PLX_INTCSR_REG; | ||
473 | subdevice->ctrl_reg = me1400_reg_base + ME1400AB_EXT_IRQ_CTRL_REG; | ||
474 | #ifdef MEDEBUG_DEBUG_REG | ||
475 | subdevice->reg_base = me1400_reg_base; | ||
476 | #endif | ||
477 | |||
478 | // Enable IRQ on PLX | ||
479 | tmp = | ||
480 | inb(subdevice-> | ||
481 | plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | | ||
482 | PLX_PCI_INT_EN); | ||
483 | outb(tmp, subdevice->plx_intcs_reg); | ||
484 | PDEBUG_REG("ctrl_reg outb(Pplx:0x%lX)=0x%x\n", subdevice->plx_intcs_reg, | ||
485 | tmp); | ||
486 | |||
487 | /* Initialize the subdevice methods */ | ||
488 | subdevice->base.me_subdevice_io_irq_start = me1400_ext_irq_io_irq_start; | ||
489 | subdevice->base.me_subdevice_io_irq_wait = me1400_ext_irq_io_irq_wait; | ||
490 | subdevice->base.me_subdevice_io_irq_stop = me1400_ext_irq_io_irq_stop; | ||
491 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
492 | me1400_ext_irq_io_reset_subdevice; | ||
493 | subdevice->base.me_subdevice_query_number_channels = | ||
494 | me1400_ext_irq_query_number_channels; | ||
495 | subdevice->base.me_subdevice_query_subdevice_type = | ||
496 | me1400_ext_irq_query_subdevice_type; | ||
497 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
498 | me1400_ext_irq_query_subdevice_caps; | ||
499 | subdevice->base.me_subdevice_query_subdevice_caps_args = | ||
500 | me1400_ext_irq_query_subdevice_caps_args; | ||
501 | subdevice->base.me_subdevice_destructor = me1400_ext_irq_destructor; | ||
502 | |||
503 | subdevice->rised = 0; | ||
504 | subdevice->n = 0; | ||
505 | |||
506 | return subdevice; | ||
507 | } | ||
diff --git a/drivers/staging/meilhaus/me1400_ext_irq.h b/drivers/staging/meilhaus/me1400_ext_irq.h deleted file mode 100644 index 9b72a04701c0..000000000000 --- a/drivers/staging/meilhaus/me1400_ext_irq.h +++ /dev/null | |||
@@ -1,62 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1400_ext_irq.h | ||
3 | * | ||
4 | * @brief ME-1400 external interrupt implementation. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME1400_EXT_IRQ_H_ | ||
10 | #define _ME1400_EXT_IRQ_H_ | ||
11 | |||
12 | #include <linux/sched.h> | ||
13 | |||
14 | #include "mesubdevice.h" | ||
15 | #include "meslock.h" | ||
16 | |||
17 | #ifdef __KERNEL__ | ||
18 | |||
19 | /** | ||
20 | * @brief The ME-1400 external interrupt subdevice class. | ||
21 | */ | ||
22 | typedef struct me1400_ext_irq_subdevice { | ||
23 | /* Inheritance */ | ||
24 | me_subdevice_t base; /**< The subdevice base class. */ | ||
25 | |||
26 | /* Attributes */ | ||
27 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
28 | spinlock_t *clk_src_reg_lock; /**< Lock protecting the clock control register. */ | ||
29 | |||
30 | wait_queue_head_t wait_queue; /**< Queue to put on threads waiting for an interrupt. */ | ||
31 | |||
32 | uint32_t device_id; /**< The device id of the device holding the subdevice. */ | ||
33 | int irq; /**< The irq number assigned by PCI BIOS. */ | ||
34 | int rised; /**< If true an interrupt has occured. */ | ||
35 | unsigned int n; /**< The number of interrupt since the driver was loaded. */ | ||
36 | |||
37 | unsigned long plx_intcs_reg; /**< The PLX interrupt control and status register. */ | ||
38 | unsigned long ctrl_reg; /**< The control register. */ | ||
39 | #ifdef MEDEBUG_DEBUG_REG | ||
40 | unsigned long reg_base; | ||
41 | #endif | ||
42 | } me1400_ext_irq_subdevice_t; | ||
43 | |||
44 | /** | ||
45 | * @brief The constructor to generate a ME-1400 external interrupt instance. | ||
46 | * | ||
47 | * @param plx_reg_base The register base address of the PLX chip as returned by the PCI BIOS. | ||
48 | * @param me1400_reg_base The register base address of the ME-1400 device as returned by the PCI BIOS. | ||
49 | * @param irq The irq assigned by the PCI BIOS. | ||
50 | * | ||
51 | * @return Pointer to new instance on success.\n | ||
52 | * NULL on error. | ||
53 | */ | ||
54 | me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id, | ||
55 | uint32_t plx_reg_base, | ||
56 | uint32_t me1400_reg_base, | ||
57 | spinlock_t * | ||
58 | clk_src_reg_lock, | ||
59 | int irq); | ||
60 | |||
61 | #endif | ||
62 | #endif | ||
diff --git a/drivers/staging/meilhaus/me1400_ext_irq_reg.h b/drivers/staging/meilhaus/me1400_ext_irq_reg.h deleted file mode 100644 index c9740f2dd3a7..000000000000 --- a/drivers/staging/meilhaus/me1400_ext_irq_reg.h +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1400_ext_irq_reg.h | ||
3 | * | ||
4 | * @brief ME-1400 external interrupt register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef _ME1400_EXT_IRQ_REG_H_ | ||
29 | # define _ME1400_EXT_IRQ_REG_H_ | ||
30 | |||
31 | # ifdef __KERNEL__ | ||
32 | |||
33 | # define PLX_INTCSR_REG 0x4C /**< The PLX interrupt control and status register offset. */ | ||
34 | # define PLX_ICR_REG 0x50 /**< The PLX initialization control register offset. */ | ||
35 | |||
36 | # define PLX_LOCAL_INT1_EN 0x01 /**< If set the local interrupt 1 is enabled. */ | ||
37 | # define PLX_LOCAL_INT1_POL 0x02 /**< If set the local interrupt 1 polarity is high active. */ | ||
38 | # define PLX_LOCAL_INT1_STATE 0x04 /**< If set the local interrupt 1 is activ. */ | ||
39 | # define PLX_LOCAL_INT2_EN 0x08 /**< If set the local interrupt 2 is enabled. */ | ||
40 | # define PLX_LOCAL_INT2_POL 0x10 /**< If set the local interrupt 2 polarity is high active. */ | ||
41 | # define PLX_LOCAL_INT2_STATE 0x20 /**< If set the local interrupt 2 is activ. */ | ||
42 | # define PLX_PCI_INT_EN 0x40 /**< If set the PCI interrupt is enabled. */ | ||
43 | # define PLX_SOFT_INT 0x80 /**< If set an interrupt is generated. */ | ||
44 | |||
45 | # define ME1400AB_EXT_IRQ_CTRL_REG 0x11 /**< The external interrupt control register offset. */ | ||
46 | |||
47 | # define ME1400AB_EXT_IRQ_CLK_EN 0x01 /**< If this bit is set, the clock output is enabled. */ | ||
48 | # define ME1400AB_EXT_IRQ_IRQ_EN 0x02 /**< If set the external interrupt is enabled. Clearing this bit clears a pending interrupt. */ | ||
49 | |||
50 | # define ME1400CD_EXT_IRQ_CTRL_REG 0x11 /**< The external interrupt control register offset. */ | ||
51 | |||
52 | # define ME1400CD_EXT_IRQ_CLK_EN 0x10 /**< If set the external interrupt is enabled. Clearing this bit clears a pending interrupt.*/ | ||
53 | |||
54 | # endif //__KERNEL__ | ||
55 | |||
56 | #endif //_ME1400_EXT_IRQ_REG_H_ | ||
diff --git a/drivers/staging/meilhaus/me1600_ao.c b/drivers/staging/meilhaus/me1600_ao.c deleted file mode 100644 index 12e3c70e982a..000000000000 --- a/drivers/staging/meilhaus/me1600_ao.c +++ /dev/null | |||
@@ -1,1017 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1600_ao.c | ||
3 | * | ||
4 | * @brief ME-1600 analog output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* Includes | ||
33 | */ | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | #include <linux/sched.h> | ||
42 | |||
43 | #include <linux/workqueue.h> | ||
44 | |||
45 | #include "medefines.h" | ||
46 | #include "meinternal.h" | ||
47 | #include "meerror.h" | ||
48 | #include "medebug.h" | ||
49 | |||
50 | #include "me1600_ao_reg.h" | ||
51 | #include "me1600_ao.h" | ||
52 | |||
53 | /* Defines | ||
54 | */ | ||
55 | |||
56 | static void me1600_ao_destructor(struct me_subdevice *subdevice); | ||
57 | |||
58 | static void me1600_ao_work_control_task(struct work_struct *work); | ||
59 | |||
60 | static int me1600_ao_io_reset_subdevice(me_subdevice_t *subdevice, | ||
61 | struct file *filep, int flags); | ||
62 | static int me1600_ao_io_single_config(me_subdevice_t *subdevice, | ||
63 | struct file *filep, int channel, | ||
64 | int single_config, int ref, int trig_chan, | ||
65 | int trig_type, int trig_edge, int flags); | ||
66 | static int me1600_ao_io_single_read(me_subdevice_t *subdevice, | ||
67 | struct file *filep, int channel, int *value, | ||
68 | int time_out, int flags); | ||
69 | static int me1600_ao_io_single_write(me_subdevice_t *subdevice, | ||
70 | struct file *filep, int channel, int value, | ||
71 | int time_out, int flags); | ||
72 | static int me1600_ao_query_number_channels(me_subdevice_t *subdevice, | ||
73 | int *number); | ||
74 | static int me1600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, | ||
75 | int *subtype); | ||
76 | static int me1600_ao_query_subdevice_caps(me_subdevice_t *subdevice, | ||
77 | int *caps); | ||
78 | static int me1600_ao_query_range_by_min_max(me_subdevice_t *subdevice, | ||
79 | int unit, int *min, int *max, | ||
80 | int *maxdata, int *range); | ||
81 | static int me1600_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, | ||
82 | int *count); | ||
83 | static int me1600_ao_query_range_info(me_subdevice_t *subdevice, int range, | ||
84 | int *unit, int *min, int *max, | ||
85 | int *maxdata); | ||
86 | |||
87 | /* Functions | ||
88 | */ | ||
89 | |||
90 | me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base, | ||
91 | unsigned int ao_idx, | ||
92 | int curr, | ||
93 | spinlock_t *config_regs_lock, | ||
94 | spinlock_t *ao_shadows_lock, | ||
95 | me1600_ao_shadow_t *ao_regs_shadows, | ||
96 | struct workqueue_struct *me1600_wq) | ||
97 | { | ||
98 | me1600_ao_subdevice_t *subdevice; | ||
99 | int err; | ||
100 | |||
101 | PDEBUG("executed. idx=%d\n", ao_idx); | ||
102 | |||
103 | // Allocate memory for subdevice instance. | ||
104 | subdevice = kmalloc(sizeof(me1600_ao_subdevice_t), GFP_KERNEL); | ||
105 | |||
106 | if (!subdevice) { | ||
107 | PERROR | ||
108 | ("Cannot get memory for analog output subdevice instance.\n"); | ||
109 | return NULL; | ||
110 | } | ||
111 | |||
112 | memset(subdevice, 0, sizeof(me1600_ao_subdevice_t)); | ||
113 | |||
114 | // Initialize subdevice base class. | ||
115 | err = me_subdevice_init(&subdevice->base); | ||
116 | |||
117 | if (err) { | ||
118 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
119 | kfree(subdevice); | ||
120 | return NULL; | ||
121 | } | ||
122 | // Initialize spin locks. | ||
123 | spin_lock_init(&subdevice->subdevice_lock); | ||
124 | subdevice->config_regs_lock = config_regs_lock; | ||
125 | subdevice->ao_shadows_lock = ao_shadows_lock; | ||
126 | |||
127 | // Save the subdevice index. | ||
128 | subdevice->ao_idx = ao_idx; | ||
129 | |||
130 | // Initialize range lists. | ||
131 | subdevice->u_ranges_count = 2; | ||
132 | |||
133 | subdevice->u_ranges[0].min = 0; //0V | ||
134 | subdevice->u_ranges[0].max = 9997558; //10V | ||
135 | |||
136 | subdevice->u_ranges[1].min = -10E6; //-10V | ||
137 | subdevice->u_ranges[1].max = 9995117; //10V | ||
138 | |||
139 | if (curr) { // This is version with current outputs. | ||
140 | subdevice->i_ranges_count = 2; | ||
141 | |||
142 | subdevice->i_ranges[0].min = 0; //0mA | ||
143 | subdevice->i_ranges[0].max = 19995117; //20mA | ||
144 | |||
145 | subdevice->i_ranges[1].min = 4E3; //4mA | ||
146 | subdevice->i_ranges[1].max = 19995118; //20mA | ||
147 | } else { // This is version without current outputs. | ||
148 | subdevice->i_ranges_count = 0; | ||
149 | |||
150 | subdevice->i_ranges[0].min = 0; //0mA | ||
151 | subdevice->i_ranges[0].max = 0; //0mA | ||
152 | |||
153 | subdevice->i_ranges[1].min = 0; //0mA | ||
154 | subdevice->i_ranges[1].max = 0; //0mA | ||
155 | } | ||
156 | |||
157 | // Initialize registers. | ||
158 | subdevice->uni_bi_reg = reg_base + ME1600_UNI_BI_REG; | ||
159 | subdevice->i_range_reg = reg_base + ME1600_020_420_REG; | ||
160 | subdevice->sim_output_reg = reg_base + ME1600_SIM_OUTPUT_REG; | ||
161 | subdevice->current_on_reg = reg_base + ME1600_CURRENT_ON_REG; | ||
162 | #ifdef MEDEBUG_DEBUG_REG | ||
163 | subdevice->reg_base = reg_base; | ||
164 | #endif | ||
165 | |||
166 | // Initialize shadow structure. | ||
167 | subdevice->ao_regs_shadows = ao_regs_shadows; | ||
168 | |||
169 | // Override base class methods. | ||
170 | subdevice->base.me_subdevice_destructor = me1600_ao_destructor; | ||
171 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
172 | me1600_ao_io_reset_subdevice; | ||
173 | subdevice->base.me_subdevice_io_single_config = | ||
174 | me1600_ao_io_single_config; | ||
175 | subdevice->base.me_subdevice_io_single_read = me1600_ao_io_single_read; | ||
176 | subdevice->base.me_subdevice_io_single_write = | ||
177 | me1600_ao_io_single_write; | ||
178 | subdevice->base.me_subdevice_query_number_channels = | ||
179 | me1600_ao_query_number_channels; | ||
180 | subdevice->base.me_subdevice_query_subdevice_type = | ||
181 | me1600_ao_query_subdevice_type; | ||
182 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
183 | me1600_ao_query_subdevice_caps; | ||
184 | subdevice->base.me_subdevice_query_range_by_min_max = | ||
185 | me1600_ao_query_range_by_min_max; | ||
186 | subdevice->base.me_subdevice_query_number_ranges = | ||
187 | me1600_ao_query_number_ranges; | ||
188 | subdevice->base.me_subdevice_query_range_info = | ||
189 | me1600_ao_query_range_info; | ||
190 | |||
191 | // Initialize wait queue. | ||
192 | init_waitqueue_head(&subdevice->wait_queue); | ||
193 | |||
194 | // Prepare work queue. | ||
195 | subdevice->me1600_workqueue = me1600_wq; | ||
196 | |||
197 | /* workqueue API changed in kernel 2.6.20 */ | ||
198 | INIT_DELAYED_WORK(&subdevice->ao_control_task, | ||
199 | me1600_ao_work_control_task); | ||
200 | return subdevice; | ||
201 | } | ||
202 | |||
203 | static void me1600_ao_destructor(struct me_subdevice *subdevice) | ||
204 | { | ||
205 | me1600_ao_subdevice_t *instance; | ||
206 | |||
207 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
208 | |||
209 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
210 | |||
211 | instance->ao_control_task_flag = 0; | ||
212 | |||
213 | // Reset subdevice to asure clean exit. | ||
214 | me1600_ao_io_reset_subdevice(subdevice, NULL, | ||
215 | ME_IO_RESET_SUBDEVICE_NO_FLAGS); | ||
216 | |||
217 | // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). | ||
218 | if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. | ||
219 | set_current_state(TASK_INTERRUPTIBLE); | ||
220 | schedule_timeout(2); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | static int me1600_ao_io_reset_subdevice(me_subdevice_t *subdevice, | ||
225 | struct file *filep, int flags) | ||
226 | { | ||
227 | me1600_ao_subdevice_t *instance; | ||
228 | uint16_t tmp; | ||
229 | |||
230 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
231 | |||
232 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
233 | |||
234 | if (flags) { | ||
235 | PERROR("Invalid flag specified.\n"); | ||
236 | return ME_ERRNO_INVALID_FLAGS; | ||
237 | } | ||
238 | |||
239 | ME_SUBDEVICE_ENTER; | ||
240 | |||
241 | //Cancel control task | ||
242 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
243 | instance->ao_control_task_flag = 0; | ||
244 | cancel_delayed_work(&instance->ao_control_task); | ||
245 | (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger. | ||
246 | |||
247 | // Reset all settings. | ||
248 | spin_lock(&instance->subdevice_lock); | ||
249 | spin_lock(instance->ao_shadows_lock); | ||
250 | (instance->ao_regs_shadows)->shadow[instance->ao_idx] = 0; | ||
251 | (instance->ao_regs_shadows)->mirror[instance->ao_idx] = 0; | ||
252 | (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Not waiting for triggering. | ||
253 | (instance->ao_regs_shadows)->synchronous &= ~(0x1 << instance->ao_idx); //Individual triggering. | ||
254 | |||
255 | // Set output to default (safe) state. | ||
256 | spin_lock(instance->config_regs_lock); | ||
257 | tmp = inw(instance->uni_bi_reg); // unipolar | ||
258 | tmp |= (0x1 << instance->ao_idx); | ||
259 | outw(tmp, instance->uni_bi_reg); | ||
260 | PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
261 | instance->uni_bi_reg - instance->reg_base, tmp); | ||
262 | |||
263 | tmp = inw(instance->current_on_reg); // Volts only! | ||
264 | tmp &= ~(0x1 << instance->ao_idx); | ||
265 | tmp &= 0x00FF; | ||
266 | outw(tmp, instance->current_on_reg); | ||
267 | PDEBUG_REG("current_on_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
268 | instance->reg_base, | ||
269 | instance->current_on_reg - instance->reg_base, tmp); | ||
270 | |||
271 | tmp = inw(instance->i_range_reg); // 0..20mA <= If exists. | ||
272 | tmp &= ~(0x1 << instance->ao_idx); | ||
273 | outw(tmp, instance->i_range_reg); | ||
274 | PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
275 | instance->i_range_reg - instance->reg_base, tmp); | ||
276 | |||
277 | outw(0, (instance->ao_regs_shadows)->registry[instance->ao_idx]); | ||
278 | PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
279 | (instance->ao_regs_shadows)->registry[instance->ao_idx] - | ||
280 | instance->reg_base, 0); | ||
281 | |||
282 | // Trigger output. | ||
283 | outw(0x0000, instance->sim_output_reg); | ||
284 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
285 | instance->reg_base, | ||
286 | instance->sim_output_reg - instance->reg_base, 0x0000); | ||
287 | outw(0xFFFF, instance->sim_output_reg); | ||
288 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
289 | instance->reg_base, | ||
290 | instance->sim_output_reg - instance->reg_base, 0xFFFF); | ||
291 | spin_unlock(instance->config_regs_lock); | ||
292 | spin_unlock(instance->ao_shadows_lock); | ||
293 | |||
294 | // Set status to 'none' | ||
295 | instance->status = ao_status_none; | ||
296 | spin_unlock(&instance->subdevice_lock); | ||
297 | |||
298 | //Signal reset if user is on wait. | ||
299 | wake_up_interruptible_all(&instance->wait_queue); | ||
300 | |||
301 | ME_SUBDEVICE_EXIT; | ||
302 | |||
303 | return ME_ERRNO_SUCCESS; | ||
304 | } | ||
305 | |||
306 | static int me1600_ao_io_single_config(me_subdevice_t *subdevice, | ||
307 | struct file *filep, | ||
308 | int channel, | ||
309 | int single_config, | ||
310 | int ref, | ||
311 | int trig_chan, | ||
312 | int trig_type, int trig_edge, int flags) | ||
313 | { | ||
314 | me1600_ao_subdevice_t *instance; | ||
315 | uint16_t tmp; | ||
316 | |||
317 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
318 | |||
319 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
320 | |||
321 | // Checking parameters. | ||
322 | if (flags) { | ||
323 | PERROR | ||
324 | ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n"); | ||
325 | return ME_ERRNO_INVALID_FLAGS; | ||
326 | } | ||
327 | |||
328 | if (trig_edge != ME_TRIG_EDGE_NONE) { | ||
329 | PERROR | ||
330 | ("Invalid trigger edge. Software trigger has not edge. Must be ME_TRIG_EDGE_NONE\n"); | ||
331 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
332 | } | ||
333 | |||
334 | if (trig_type != ME_TRIG_TYPE_SW) { | ||
335 | PERROR("Invalid trigger edge. Must be ME_TRIG_TYPE_SW.\n"); | ||
336 | return ME_ERRNO_INVALID_TRIG_TYPE; | ||
337 | } | ||
338 | |||
339 | if ((trig_chan != ME_TRIG_CHAN_DEFAULT) | ||
340 | && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) { | ||
341 | PERROR("Invalid trigger channel specified.\n"); | ||
342 | return ME_ERRNO_INVALID_TRIG_CHAN; | ||
343 | } | ||
344 | |||
345 | if (ref != ME_REF_AO_GROUND) { | ||
346 | PERROR | ||
347 | ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n"); | ||
348 | return ME_ERRNO_INVALID_REF; | ||
349 | } | ||
350 | |||
351 | if (((single_config + 1) > | ||
352 | (instance->u_ranges_count + instance->i_ranges_count)) | ||
353 | || (single_config < 0)) { | ||
354 | PERROR("Invalid range specified.\n"); | ||
355 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
356 | } | ||
357 | |||
358 | if (channel) { | ||
359 | PERROR("Invalid channel specified.\n"); | ||
360 | return ME_ERRNO_INVALID_CHANNEL; | ||
361 | } | ||
362 | // Checking parameters - done. All is fine. Do config. | ||
363 | |||
364 | ME_SUBDEVICE_ENTER; | ||
365 | |||
366 | //Cancel control task | ||
367 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
368 | instance->ao_control_task_flag = 0; | ||
369 | cancel_delayed_work(&instance->ao_control_task); | ||
370 | |||
371 | spin_lock(&instance->subdevice_lock); | ||
372 | spin_lock(instance->ao_shadows_lock); | ||
373 | (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger. | ||
374 | (instance->ao_regs_shadows)->shadow[instance->ao_idx] = 0; | ||
375 | (instance->ao_regs_shadows)->mirror[instance->ao_idx] = 0; | ||
376 | |||
377 | spin_lock(instance->config_regs_lock); | ||
378 | switch (single_config) { | ||
379 | case 0: // 0V 10V | ||
380 | tmp = inw(instance->current_on_reg); // Volts | ||
381 | tmp &= ~(0x1 << instance->ao_idx); | ||
382 | outw(tmp, instance->current_on_reg); | ||
383 | PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
384 | instance->reg_base, | ||
385 | instance->current_on_reg - instance->reg_base, tmp); | ||
386 | |||
387 | // 0V | ||
388 | outw(0, | ||
389 | (instance->ao_regs_shadows)->registry[instance->ao_idx]); | ||
390 | PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
391 | instance->reg_base, | ||
392 | (instance->ao_regs_shadows)->registry[instance-> | ||
393 | ao_idx] - | ||
394 | instance->reg_base, 0); | ||
395 | |||
396 | tmp = inw(instance->uni_bi_reg); // unipolar | ||
397 | tmp |= (0x1 << instance->ao_idx); | ||
398 | outw(tmp, instance->uni_bi_reg); | ||
399 | PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
400 | instance->reg_base, | ||
401 | instance->uni_bi_reg - instance->reg_base, tmp); | ||
402 | |||
403 | tmp = inw(instance->i_range_reg); // 0..20mA <= If exists. | ||
404 | tmp &= ~(0x1 << instance->ao_idx); | ||
405 | outw(tmp, instance->i_range_reg); | ||
406 | PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
407 | instance->reg_base, | ||
408 | instance->i_range_reg - instance->reg_base, tmp); | ||
409 | break; | ||
410 | |||
411 | case 1: // -10V 10V | ||
412 | tmp = inw(instance->current_on_reg); // Volts | ||
413 | tmp &= ~(0x1 << instance->ao_idx); | ||
414 | outw(tmp, instance->current_on_reg); | ||
415 | PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
416 | instance->reg_base, | ||
417 | instance->current_on_reg - instance->reg_base, tmp); | ||
418 | |||
419 | // 0V | ||
420 | outw(0x0800, | ||
421 | (instance->ao_regs_shadows)->registry[instance->ao_idx]); | ||
422 | PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
423 | instance->reg_base, | ||
424 | (instance->ao_regs_shadows)->registry[instance-> | ||
425 | ao_idx] - | ||
426 | instance->reg_base, 0x0800); | ||
427 | |||
428 | tmp = inw(instance->uni_bi_reg); // bipolar | ||
429 | tmp &= ~(0x1 << instance->ao_idx); | ||
430 | outw(tmp, instance->uni_bi_reg); | ||
431 | PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
432 | instance->reg_base, | ||
433 | instance->uni_bi_reg - instance->reg_base, tmp); | ||
434 | |||
435 | tmp = inw(instance->i_range_reg); // 0..20mA <= If exists. | ||
436 | tmp &= ~(0x1 << instance->ao_idx); | ||
437 | outw(tmp, instance->i_range_reg); | ||
438 | PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
439 | instance->reg_base, | ||
440 | instance->i_range_reg - instance->reg_base, tmp); | ||
441 | break; | ||
442 | |||
443 | case 2: // 0mA 20mA | ||
444 | tmp = inw(instance->current_on_reg); // mAmpers | ||
445 | tmp |= (0x1 << instance->ao_idx); | ||
446 | outw(tmp, instance->current_on_reg); | ||
447 | PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
448 | instance->reg_base, | ||
449 | instance->current_on_reg - instance->reg_base, tmp); | ||
450 | |||
451 | tmp = inw(instance->i_range_reg); // 0..20mA | ||
452 | tmp &= ~(0x1 << instance->ao_idx); | ||
453 | outw(tmp, instance->i_range_reg); | ||
454 | PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
455 | instance->reg_base, | ||
456 | instance->i_range_reg - instance->reg_base, tmp); | ||
457 | |||
458 | // 0mA | ||
459 | outw(0, | ||
460 | (instance->ao_regs_shadows)->registry[instance->ao_idx]); | ||
461 | PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
462 | instance->reg_base, | ||
463 | (instance->ao_regs_shadows)->registry[instance-> | ||
464 | ao_idx] - | ||
465 | instance->reg_base, 0); | ||
466 | |||
467 | tmp = inw(instance->uni_bi_reg); // unipolar | ||
468 | tmp |= (0x1 << instance->ao_idx); | ||
469 | outw(tmp, instance->uni_bi_reg); | ||
470 | PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
471 | instance->reg_base, | ||
472 | instance->uni_bi_reg - instance->reg_base, tmp); | ||
473 | break; | ||
474 | |||
475 | case 3: // 4mA 20mA | ||
476 | tmp = inw(instance->current_on_reg); // mAmpers | ||
477 | tmp |= (0x1 << instance->ao_idx); | ||
478 | outw(tmp, instance->current_on_reg); | ||
479 | PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
480 | instance->reg_base, | ||
481 | instance->current_on_reg - instance->reg_base, tmp); | ||
482 | |||
483 | tmp = inw(instance->i_range_reg); // 4..20mA | ||
484 | tmp |= (0x1 << instance->ao_idx); | ||
485 | outw(tmp, instance->i_range_reg); | ||
486 | PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
487 | instance->reg_base, | ||
488 | instance->i_range_reg - instance->reg_base, tmp); | ||
489 | |||
490 | // 4mA | ||
491 | outw(0, | ||
492 | (instance->ao_regs_shadows)->registry[instance->ao_idx]); | ||
493 | PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
494 | instance->reg_base, | ||
495 | (instance->ao_regs_shadows)->registry[instance-> | ||
496 | ao_idx] - | ||
497 | instance->reg_base, 0); | ||
498 | |||
499 | tmp = inw(instance->uni_bi_reg); // unipolar | ||
500 | tmp |= (0x1 << instance->ao_idx); | ||
501 | outw(tmp, instance->uni_bi_reg); | ||
502 | PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
503 | instance->reg_base, | ||
504 | instance->uni_bi_reg - instance->reg_base, tmp); | ||
505 | break; | ||
506 | } | ||
507 | |||
508 | // Trigger output. | ||
509 | outw(0x0000, instance->sim_output_reg); | ||
510 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
511 | instance->reg_base, | ||
512 | instance->sim_output_reg - instance->reg_base, 0x0000); | ||
513 | outw(0xFFFF, instance->sim_output_reg); | ||
514 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
515 | instance->reg_base, | ||
516 | instance->sim_output_reg - instance->reg_base, 0xFFFF); | ||
517 | |||
518 | if (trig_chan == ME_TRIG_CHAN_DEFAULT) { // Individual triggering. | ||
519 | (instance->ao_regs_shadows)->synchronous &= | ||
520 | ~(0x1 << instance->ao_idx); | ||
521 | PDEBUG("Individual triggering.\n"); | ||
522 | } else if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS) { // Synchronous triggering. | ||
523 | (instance->ao_regs_shadows)->synchronous |= | ||
524 | (0x1 << instance->ao_idx); | ||
525 | PDEBUG("Synchronous triggering.\n"); | ||
526 | } | ||
527 | spin_unlock(instance->config_regs_lock); | ||
528 | spin_unlock(instance->ao_shadows_lock); | ||
529 | |||
530 | instance->status = ao_status_single_configured; | ||
531 | spin_unlock(&instance->subdevice_lock); | ||
532 | |||
533 | ME_SUBDEVICE_EXIT; | ||
534 | |||
535 | return ME_ERRNO_SUCCESS; | ||
536 | } | ||
537 | |||
538 | static int me1600_ao_io_single_read(me_subdevice_t *subdevice, | ||
539 | struct file *filep, | ||
540 | int channel, | ||
541 | int *value, int time_out, int flags) | ||
542 | { | ||
543 | me1600_ao_subdevice_t *instance; | ||
544 | unsigned long delay = 0; | ||
545 | unsigned long j = 0; | ||
546 | int err = ME_ERRNO_SUCCESS; | ||
547 | |||
548 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
549 | |||
550 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
551 | |||
552 | if (flags & ~ME_IO_SINGLE_NONBLOCKING) { | ||
553 | PERROR("Invalid flag specified. %d\n", flags); | ||
554 | return ME_ERRNO_INVALID_FLAGS; | ||
555 | } | ||
556 | |||
557 | if (time_out < 0) { | ||
558 | PERROR("Invalid timeout specified.\n"); | ||
559 | return ME_ERRNO_INVALID_TIMEOUT; | ||
560 | } | ||
561 | |||
562 | if (channel) { | ||
563 | PERROR("Invalid channel specified.\n"); | ||
564 | return ME_ERRNO_INVALID_CHANNEL; | ||
565 | } | ||
566 | |||
567 | if ((!flags) && ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { //Blocking mode. Wait for software trigger. | ||
568 | if (time_out) { | ||
569 | delay = (time_out * HZ) / 1000; | ||
570 | if (delay == 0) | ||
571 | delay = 1; | ||
572 | } | ||
573 | |||
574 | j = jiffies; | ||
575 | |||
576 | //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. | ||
577 | wait_event_interruptible_timeout(instance->wait_queue, | ||
578 | (!((instance-> | ||
579 | ao_regs_shadows)-> | ||
580 | trigger & instance-> | ||
581 | ao_idx)), | ||
582 | (delay) ? delay : LONG_MAX); | ||
583 | |||
584 | if (instance == ao_status_none) { // Reset was called. | ||
585 | PDEBUG("Single canceled.\n"); | ||
586 | err = ME_ERRNO_CANCELLED; | ||
587 | } | ||
588 | |||
589 | if (signal_pending(current)) { | ||
590 | PERROR("Wait on start of state machine interrupted.\n"); | ||
591 | err = ME_ERRNO_SIGNAL; | ||
592 | } | ||
593 | |||
594 | if ((delay) && ((jiffies - j) >= delay)) { | ||
595 | PDEBUG("Timeout reached.\n"); | ||
596 | err = ME_ERRNO_TIMEOUT; | ||
597 | } | ||
598 | } | ||
599 | |||
600 | *value = (instance->ao_regs_shadows)->mirror[instance->ao_idx]; | ||
601 | |||
602 | return err; | ||
603 | } | ||
604 | |||
605 | static int me1600_ao_io_single_write(me_subdevice_t *subdevice, | ||
606 | struct file *filep, | ||
607 | int channel, | ||
608 | int value, int time_out, int flags) | ||
609 | { | ||
610 | me1600_ao_subdevice_t *instance; | ||
611 | int err = ME_ERRNO_SUCCESS; | ||
612 | unsigned long delay = 0; | ||
613 | int i; | ||
614 | unsigned long j = 0; | ||
615 | |||
616 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
617 | |||
618 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
619 | |||
620 | if (flags & | ||
621 | ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS | | ||
622 | ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { | ||
623 | PERROR("Invalid flag specified.\n"); | ||
624 | return ME_ERRNO_INVALID_FLAGS; | ||
625 | } | ||
626 | |||
627 | if (time_out < 0) { | ||
628 | PERROR("Invalid timeout specified.\n"); | ||
629 | return ME_ERRNO_INVALID_TIMEOUT; | ||
630 | } | ||
631 | |||
632 | if (value & ~ME1600_AO_MAX_DATA) { | ||
633 | PERROR("Invalid value provided.\n"); | ||
634 | return ME_ERRNO_VALUE_OUT_OF_RANGE; | ||
635 | } | ||
636 | |||
637 | if (channel) { | ||
638 | PERROR("Invalid channel specified.\n"); | ||
639 | return ME_ERRNO_INVALID_CHANNEL; | ||
640 | } | ||
641 | |||
642 | ME_SUBDEVICE_ENTER; | ||
643 | |||
644 | //Cancel control task | ||
645 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
646 | instance->ao_control_task_flag = 0; | ||
647 | cancel_delayed_work(&instance->ao_control_task); | ||
648 | (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger. | ||
649 | |||
650 | if (time_out) { | ||
651 | delay = (time_out * HZ) / 1000; | ||
652 | |||
653 | if (delay == 0) | ||
654 | delay = 1; | ||
655 | } | ||
656 | //Write value. | ||
657 | spin_lock(instance->ao_shadows_lock); | ||
658 | (instance->ao_regs_shadows)->shadow[instance->ao_idx] = | ||
659 | (uint16_t) value; | ||
660 | |||
661 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { // Trigger all outputs from synchronous list. | ||
662 | for (i = 0; i < (instance->ao_regs_shadows)->count; i++) { | ||
663 | if (((instance->ao_regs_shadows)->synchronous & (0x1 << i)) || (i == instance->ao_idx)) { // Set all from synchronous list to correct state. | ||
664 | PDEBUG | ||
665 | ("Synchronous triggering: output %d. idx=%d\n", | ||
666 | i, instance->ao_idx); | ||
667 | (instance->ao_regs_shadows)->mirror[i] = | ||
668 | (instance->ao_regs_shadows)->shadow[i]; | ||
669 | |||
670 | outw((instance->ao_regs_shadows)->shadow[i], | ||
671 | (instance->ao_regs_shadows)->registry[i]); | ||
672 | PDEBUG_REG | ||
673 | ("channel_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
674 | instance->reg_base, | ||
675 | (instance->ao_regs_shadows)->registry[i] - | ||
676 | instance->reg_base, | ||
677 | (instance->ao_regs_shadows)->shadow[i]); | ||
678 | |||
679 | (instance->ao_regs_shadows)->trigger &= | ||
680 | ~(0x1 << i); | ||
681 | } | ||
682 | } | ||
683 | |||
684 | // Trigger output. | ||
685 | outw(0x0000, instance->sim_output_reg); | ||
686 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
687 | instance->reg_base, | ||
688 | instance->sim_output_reg - instance->reg_base, 0); | ||
689 | outw(0xFFFF, instance->sim_output_reg); | ||
690 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
691 | instance->reg_base, | ||
692 | instance->sim_output_reg - instance->reg_base, | ||
693 | 0xFFFF); | ||
694 | instance->status = ao_status_single_end; | ||
695 | } else { // Individual mode. | ||
696 | if ((instance->ao_regs_shadows)->synchronous & (0x1 << instance->ao_idx)) { // Put on synchronous start list. Set output as waiting for trigger. | ||
697 | PDEBUG("Add to synchronous list. idx=%d\n", | ||
698 | instance->ao_idx); | ||
699 | (instance->ao_regs_shadows)->trigger |= | ||
700 | (0x1 << instance->ao_idx); | ||
701 | instance->status = ao_status_single_run; | ||
702 | PDEBUG("Synchronous list: 0x%x.\n", | ||
703 | (instance->ao_regs_shadows)->synchronous); | ||
704 | } else { // Fired this one. | ||
705 | PDEBUG("Triggering. idx=%d\n", instance->ao_idx); | ||
706 | (instance->ao_regs_shadows)->mirror[instance->ao_idx] = | ||
707 | (instance->ao_regs_shadows)->shadow[instance-> | ||
708 | ao_idx]; | ||
709 | |||
710 | outw((instance->ao_regs_shadows)-> | ||
711 | shadow[instance->ao_idx], | ||
712 | (instance->ao_regs_shadows)->registry[instance-> | ||
713 | ao_idx]); | ||
714 | PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
715 | instance->reg_base, | ||
716 | (instance->ao_regs_shadows)-> | ||
717 | registry[instance->ao_idx] - | ||
718 | instance->reg_base, | ||
719 | (instance->ao_regs_shadows)-> | ||
720 | shadow[instance->ao_idx]); | ||
721 | |||
722 | // Set output as triggered. | ||
723 | (instance->ao_regs_shadows)->trigger &= | ||
724 | ~(0x1 << instance->ao_idx); | ||
725 | |||
726 | // Trigger output. | ||
727 | outw(0x0000, instance->sim_output_reg); | ||
728 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
729 | instance->reg_base, | ||
730 | instance->sim_output_reg - | ||
731 | instance->reg_base, 0); | ||
732 | outw(0xFFFF, instance->sim_output_reg); | ||
733 | PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
734 | instance->reg_base, | ||
735 | instance->sim_output_reg - | ||
736 | instance->reg_base, 0xFFFF); | ||
737 | instance->status = ao_status_single_end; | ||
738 | } | ||
739 | } | ||
740 | spin_unlock(instance->ao_shadows_lock); | ||
741 | |||
742 | //Init control task | ||
743 | instance->timeout.delay = delay; | ||
744 | instance->timeout.start_time = jiffies; | ||
745 | instance->ao_control_task_flag = 1; | ||
746 | queue_delayed_work(instance->me1600_workqueue, | ||
747 | &instance->ao_control_task, 1); | ||
748 | |||
749 | if ((!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) && | ||
750 | ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { | ||
751 | /* Blocking mode. Wait for software trigger. */ | ||
752 | if (time_out) { | ||
753 | delay = (time_out * HZ) / 1000; | ||
754 | if (delay == 0) | ||
755 | delay = 1; | ||
756 | } | ||
757 | |||
758 | j = jiffies; | ||
759 | |||
760 | //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. | ||
761 | wait_event_interruptible_timeout(instance->wait_queue, | ||
762 | (!((instance-> | ||
763 | ao_regs_shadows)-> | ||
764 | trigger & instance-> | ||
765 | ao_idx)), | ||
766 | (delay) ? delay : LONG_MAX); | ||
767 | |||
768 | if (instance == ao_status_none) { | ||
769 | PDEBUG("Single canceled.\n"); | ||
770 | err = ME_ERRNO_CANCELLED; | ||
771 | } | ||
772 | if (signal_pending(current)) { | ||
773 | PERROR("Wait on start of state machine interrupted.\n"); | ||
774 | err = ME_ERRNO_SIGNAL; | ||
775 | } | ||
776 | |||
777 | if ((delay) && ((jiffies - j) >= delay)) { | ||
778 | PDEBUG("Timeout reached.\n"); | ||
779 | err = ME_ERRNO_TIMEOUT; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | ME_SUBDEVICE_EXIT; | ||
784 | |||
785 | return err; | ||
786 | } | ||
787 | |||
788 | static int me1600_ao_query_number_channels(me_subdevice_t *subdevice, | ||
789 | int *number) | ||
790 | { | ||
791 | me1600_ao_subdevice_t *instance; | ||
792 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
793 | |||
794 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
795 | |||
796 | *number = 1; //Every subdevice has only 1 channel. | ||
797 | return ME_ERRNO_SUCCESS; | ||
798 | } | ||
799 | |||
800 | static int me1600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, | ||
801 | int *subtype) | ||
802 | { | ||
803 | me1600_ao_subdevice_t *instance; | ||
804 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
805 | |||
806 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
807 | |||
808 | *type = ME_TYPE_AO; | ||
809 | *subtype = ME_SUBTYPE_SINGLE; | ||
810 | return ME_ERRNO_SUCCESS; | ||
811 | } | ||
812 | |||
813 | static int me1600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
814 | { | ||
815 | PDEBUG("executed.\n"); | ||
816 | *caps = ME_CAPS_AO_TRIG_SYNCHRONOUS; | ||
817 | return ME_ERRNO_SUCCESS; | ||
818 | } | ||
819 | |||
820 | static int me1600_ao_query_range_by_min_max(me_subdevice_t *subdevice, | ||
821 | int unit, | ||
822 | int *min, | ||
823 | int *max, int *maxdata, int *range) | ||
824 | { | ||
825 | me1600_ao_subdevice_t *instance; | ||
826 | int i; | ||
827 | int r = -1; | ||
828 | int diff = 21E6; | ||
829 | |||
830 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
831 | |||
832 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
833 | |||
834 | if ((*max - *min) < 0) { | ||
835 | PERROR("Invalid minimum and maximum values specified.\n"); | ||
836 | return ME_ERRNO_INVALID_MIN_MAX; | ||
837 | } | ||
838 | // Maximum ranges are slightly less then 10V or 20mA. For convenient we accepted this value as valid one. | ||
839 | if (unit == ME_UNIT_VOLT) { | ||
840 | for (i = 0; i < instance->u_ranges_count; i++) { | ||
841 | if ((instance->u_ranges[i].min <= *min) | ||
842 | && ((instance->u_ranges[i].max + 5000) >= *max)) { | ||
843 | if ((instance->u_ranges[i].max - | ||
844 | instance->u_ranges[i].min) - (*max - | ||
845 | *min) < | ||
846 | diff) { | ||
847 | r = i; | ||
848 | diff = | ||
849 | (instance->u_ranges[i].max - | ||
850 | instance->u_ranges[i].min) - | ||
851 | (*max - *min); | ||
852 | } | ||
853 | } | ||
854 | } | ||
855 | |||
856 | if (r < 0) { | ||
857 | PERROR("No matching range found.\n"); | ||
858 | return ME_ERRNO_NO_RANGE; | ||
859 | } else { | ||
860 | *min = instance->u_ranges[r].min; | ||
861 | *max = instance->u_ranges[r].max; | ||
862 | *range = r; | ||
863 | } | ||
864 | } else if (unit == ME_UNIT_AMPERE) { | ||
865 | for (i = 0; i < instance->i_ranges_count; i++) { | ||
866 | if ((instance->i_ranges[i].min <= *min) | ||
867 | && (instance->i_ranges[i].max + 5000 >= *max)) { | ||
868 | if ((instance->i_ranges[i].max - | ||
869 | instance->i_ranges[i].min) - (*max - | ||
870 | *min) < | ||
871 | diff) { | ||
872 | r = i; | ||
873 | diff = | ||
874 | (instance->i_ranges[i].max - | ||
875 | instance->i_ranges[i].min) - | ||
876 | (*max - *min); | ||
877 | } | ||
878 | } | ||
879 | } | ||
880 | |||
881 | if (r < 0) { | ||
882 | PERROR("No matching range found.\n"); | ||
883 | return ME_ERRNO_NO_RANGE; | ||
884 | } else { | ||
885 | *min = instance->i_ranges[r].min; | ||
886 | *max = instance->i_ranges[r].max; | ||
887 | *range = r + instance->u_ranges_count; | ||
888 | } | ||
889 | } else { | ||
890 | PERROR("Invalid physical unit specified.\n"); | ||
891 | return ME_ERRNO_INVALID_UNIT; | ||
892 | } | ||
893 | *maxdata = ME1600_AO_MAX_DATA; | ||
894 | |||
895 | return ME_ERRNO_SUCCESS; | ||
896 | } | ||
897 | |||
898 | static int me1600_ao_query_number_ranges(me_subdevice_t *subdevice, | ||
899 | int unit, int *count) | ||
900 | { | ||
901 | me1600_ao_subdevice_t *instance; | ||
902 | |||
903 | PDEBUG("executed.\n"); | ||
904 | |||
905 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
906 | switch (unit) { | ||
907 | case ME_UNIT_VOLT: | ||
908 | *count = instance->u_ranges_count; | ||
909 | break; | ||
910 | case ME_UNIT_AMPERE: | ||
911 | *count = instance->i_ranges_count; | ||
912 | break; | ||
913 | case ME_UNIT_ANY: | ||
914 | *count = instance->u_ranges_count + instance->i_ranges_count; | ||
915 | break; | ||
916 | default: | ||
917 | *count = 0; | ||
918 | } | ||
919 | |||
920 | return ME_ERRNO_SUCCESS; | ||
921 | } | ||
922 | |||
923 | static int me1600_ao_query_range_info(me_subdevice_t *subdevice, | ||
924 | int range, | ||
925 | int *unit, | ||
926 | int *min, int *max, int *maxdata) | ||
927 | { | ||
928 | me1600_ao_subdevice_t *instance; | ||
929 | |||
930 | PDEBUG("executed.\n"); | ||
931 | |||
932 | instance = (me1600_ao_subdevice_t *) subdevice; | ||
933 | |||
934 | if (((range + 1) > | ||
935 | (instance->u_ranges_count + instance->i_ranges_count)) | ||
936 | || (range < 0)) { | ||
937 | PERROR("Invalid range number specified.\n"); | ||
938 | return ME_ERRNO_INVALID_RANGE; | ||
939 | } | ||
940 | |||
941 | if (range < instance->u_ranges_count) { | ||
942 | *unit = ME_UNIT_VOLT; | ||
943 | *min = instance->u_ranges[range].min; | ||
944 | *max = instance->u_ranges[range].max; | ||
945 | } else if (range < instance->u_ranges_count + instance->i_ranges_count) { | ||
946 | *unit = ME_UNIT_AMPERE; | ||
947 | *min = instance->i_ranges[range - instance->u_ranges_count].min; | ||
948 | *max = instance->i_ranges[range - instance->u_ranges_count].max; | ||
949 | } | ||
950 | *maxdata = ME1600_AO_MAX_DATA; | ||
951 | |||
952 | return ME_ERRNO_SUCCESS; | ||
953 | } | ||
954 | |||
955 | static void me1600_ao_work_control_task(struct work_struct *work) | ||
956 | { | ||
957 | me1600_ao_subdevice_t *instance; | ||
958 | int reschedule = 1; | ||
959 | int signaling = 0; | ||
960 | |||
961 | instance = | ||
962 | container_of((void *)work, me1600_ao_subdevice_t, ao_control_task); | ||
963 | |||
964 | PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, | ||
965 | instance->ao_idx); | ||
966 | |||
967 | if (!((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { // Output was triggerd. | ||
968 | // Signal the end. | ||
969 | signaling = 1; | ||
970 | reschedule = 0; | ||
971 | if (instance->status == ao_status_single_run) { | ||
972 | instance->status = ao_status_single_end; | ||
973 | } | ||
974 | |||
975 | } else if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout | ||
976 | PDEBUG("Timeout reached.\n"); | ||
977 | spin_lock(instance->ao_shadows_lock); | ||
978 | // Restore old settings. | ||
979 | PDEBUG("Write old value back to register.\n"); | ||
980 | (instance->ao_regs_shadows)->shadow[instance->ao_idx] = | ||
981 | (instance->ao_regs_shadows)->mirror[instance->ao_idx]; | ||
982 | |||
983 | outw((instance->ao_regs_shadows)->mirror[instance->ao_idx], | ||
984 | (instance->ao_regs_shadows)->registry[instance->ao_idx]); | ||
985 | PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
986 | instance->reg_base, | ||
987 | (instance->ao_regs_shadows)->registry[instance-> | ||
988 | ao_idx] - | ||
989 | instance->reg_base, | ||
990 | (instance->ao_regs_shadows)->mirror[instance-> | ||
991 | ao_idx]); | ||
992 | |||
993 | //Remove from synchronous strt list. | ||
994 | (instance->ao_regs_shadows)->trigger &= | ||
995 | ~(0x1 << instance->ao_idx); | ||
996 | if (instance->status == ao_status_none) { | ||
997 | instance->status = ao_status_single_end; | ||
998 | } | ||
999 | spin_unlock(instance->ao_shadows_lock); | ||
1000 | |||
1001 | // Signal the end. | ||
1002 | signaling = 1; | ||
1003 | reschedule = 0; | ||
1004 | } | ||
1005 | |||
1006 | if (signaling) { //Signal it. | ||
1007 | wake_up_interruptible_all(&instance->wait_queue); | ||
1008 | } | ||
1009 | |||
1010 | if (instance->ao_control_task_flag && reschedule) { // Reschedule task | ||
1011 | queue_delayed_work(instance->me1600_workqueue, | ||
1012 | &instance->ao_control_task, 1); | ||
1013 | } else { | ||
1014 | PINFO("<%s> Ending control task.\n", __func__); | ||
1015 | } | ||
1016 | |||
1017 | } | ||
diff --git a/drivers/staging/meilhaus/me1600_ao.h b/drivers/staging/meilhaus/me1600_ao.h deleted file mode 100644 index 4827dcb4bf44..000000000000 --- a/drivers/staging/meilhaus/me1600_ao.h +++ /dev/null | |||
@@ -1,128 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1600_ao.h | ||
3 | * | ||
4 | * @brief Meilhaus ME-1600 analog output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME1600_AO_H_ | ||
28 | #define _ME1600_AO_H_ | ||
29 | |||
30 | # include <linux/version.h> | ||
31 | # include "mesubdevice.h" | ||
32 | |||
33 | # ifdef __KERNEL__ | ||
34 | |||
35 | # 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. */ | ||
36 | |||
37 | /** | ||
38 | * @brief Defines a entry in the range table. | ||
39 | */ | ||
40 | typedef struct me1600_ao_range_entry { | ||
41 | int32_t min; | ||
42 | int32_t max; | ||
43 | } me1600_ao_range_entry_t; | ||
44 | |||
45 | typedef struct me1600_ao_timeout { | ||
46 | unsigned long start_time; | ||
47 | unsigned long delay; | ||
48 | } me1600_ao_timeout_t; | ||
49 | |||
50 | typedef struct me1600_ao_shadow { | ||
51 | int count; | ||
52 | unsigned long *registry; | ||
53 | uint16_t *shadow; | ||
54 | uint16_t *mirror; | ||
55 | uint16_t synchronous; /**< Synchronization list. */ | ||
56 | uint16_t trigger; /**< Synchronization flag. */ | ||
57 | } me1600_ao_shadow_t; | ||
58 | |||
59 | typedef enum ME1600_AO_STATUS { | ||
60 | ao_status_none = 0, | ||
61 | ao_status_single_configured, | ||
62 | ao_status_single_run, | ||
63 | ao_status_single_end, | ||
64 | ao_status_last | ||
65 | } ME1600_AO_STATUS; | ||
66 | |||
67 | /** | ||
68 | * @brief The ME-1600 analog output subdevice class. | ||
69 | */ | ||
70 | typedef struct me1600_ao_subdevice { | ||
71 | /* Inheritance */ | ||
72 | me_subdevice_t base; /**< The subdevice base class. */ | ||
73 | |||
74 | /* Attributes */ | ||
75 | int ao_idx; /**< The index of the analog output subdevice on the device. */ | ||
76 | |||
77 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
78 | spinlock_t *config_regs_lock; /**< Spin lock to protect configuration registers from concurrent access. */ | ||
79 | |||
80 | int u_ranges_count; /**< The number of voltage ranges available on this subdevice. */ | ||
81 | me1600_ao_range_entry_t u_ranges[ME1600_MAX_RANGES]; /**< Array holding the voltage ranges on this subdevice. */ | ||
82 | int i_ranges_count; /**< The number of current ranges available on this subdevice. */ | ||
83 | me1600_ao_range_entry_t i_ranges[ME1600_MAX_RANGES]; /**< Array holding the current ranges on this subdevice. */ | ||
84 | |||
85 | /* Registers */ | ||
86 | unsigned long uni_bi_reg; /**< Register for switching between unipoar and bipolar output mode. */ | ||
87 | unsigned long i_range_reg; /**< Register for switching between ranges. */ | ||
88 | unsigned long sim_output_reg; /**< Register used in order to update all channels simultaneously. */ | ||
89 | unsigned long current_on_reg; /**< Register enabling current output on the fourth subdevice. */ | ||
90 | # ifdef PDEBUG_REG | ||
91 | unsigned long reg_base; | ||
92 | # endif | ||
93 | |||
94 | ME1600_AO_STATUS status; | ||
95 | me1600_ao_shadow_t *ao_regs_shadows; /**< Addresses and shadows of output's registers. */ | ||
96 | spinlock_t *ao_shadows_lock; /**< Protects the shadow's struct. */ | ||
97 | int mode; /**< Mode in witch output should works. */ | ||
98 | wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ | ||
99 | me1600_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */ | ||
100 | struct workqueue_struct *me1600_workqueue; | ||
101 | struct delayed_work ao_control_task; | ||
102 | |||
103 | volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ | ||
104 | } me1600_ao_subdevice_t; | ||
105 | |||
106 | /** | ||
107 | * @brief The constructor to generate a subdevice template instance. | ||
108 | * | ||
109 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
110 | * @param ao_idx The index of the analog output subdevice on the device. | ||
111 | * @param current Flag indicating that analog output with #ao_idx of 3 is capable of current output. | ||
112 | * @param config_regs_lock Pointer to spin lock protecting the configuration registers and from concurrent access. | ||
113 | * | ||
114 | * @return Pointer to new instance on success.\n | ||
115 | * NULL on error. | ||
116 | */ | ||
117 | me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base, | ||
118 | unsigned int ao_idx, | ||
119 | int curr, | ||
120 | spinlock_t * config_regs_lock, | ||
121 | spinlock_t * ao_shadows_lock, | ||
122 | me1600_ao_shadow_t * | ||
123 | ao_regs_shadows, | ||
124 | struct workqueue_struct | ||
125 | *me1600_wq); | ||
126 | |||
127 | # endif //__KERNEL__ | ||
128 | #endif //_ME1600_AO_H_ | ||
diff --git a/drivers/staging/meilhaus/me1600_ao_reg.h b/drivers/staging/meilhaus/me1600_ao_reg.h deleted file mode 100644 index 31e7800e8074..000000000000 --- a/drivers/staging/meilhaus/me1600_ao_reg.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1600_ao_reg.h | ||
3 | * | ||
4 | * @brief ME-1600 analog output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME1600_AO_REG_H_ | ||
28 | #define _ME1600_AO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME1600_CHANNEL_0_REG 0x00 /**< Register to set a digital value on channel 0. */ | ||
33 | #define ME1600_CHANNEL_1_REG 0x02 /**< Register to set a digital value on channel 1. */ | ||
34 | #define ME1600_CHANNEL_2_REG 0x04 /**< Register to set a digital value on channel 2. */ | ||
35 | #define ME1600_CHANNEL_3_REG 0x06 /**< Register to set a digital value on channel 3. */ | ||
36 | #define ME1600_CHANNEL_4_REG 0x08 /**< Register to set a digital value on channel 4. */ | ||
37 | #define ME1600_CHANNEL_5_REG 0x0A /**< Register to set a digital value on channel 5. */ | ||
38 | #define ME1600_CHANNEL_6_REG 0x0C /**< Register to set a digital value on channel 6. */ | ||
39 | #define ME1600_CHANNEL_7_REG 0x0E /**< Register to set a digital value on channel 7. */ | ||
40 | #define ME1600_CHANNEL_8_REG 0x10 /**< Register to set a digital value on channel 8. */ | ||
41 | #define ME1600_CHANNEL_9_REG 0x12 /**< Register to set a digital value on channel 9. */ | ||
42 | #define ME1600_CHANNEL_10_REG 0x14 /**< Register to set a digital value on channel 10. */ | ||
43 | #define ME1600_CHANNEL_11_REG 0x16 /**< Register to set a digital value on channel 11. */ | ||
44 | #define ME1600_CHANNEL_12_REG 0x18 /**< Register to set a digital value on channel 12. */ | ||
45 | #define ME1600_CHANNEL_13_REG 0x1A /**< Register to set a digital value on channel 13. */ | ||
46 | #define ME1600_CHANNEL_14_REG 0x1C /**< Register to set a digital value on channel 14. */ | ||
47 | #define ME1600_CHANNEL_15_REG 0x1E /**< Register to set a digital value on channel 15. */ | ||
48 | |||
49 | /* Every channel one bit: bipolar = 0, unipolar = 1 */ | ||
50 | #define ME1600_UNI_BI_REG 0x20 /**< Register to switch between unipolar and bipolar. */ | ||
51 | |||
52 | /* Every channel one bit (only lower 8 Bits): 0..20mA = 0, 4..20mA = 1 */ | ||
53 | #define ME1600_020_420_REG 0x22 /**< Register to switch between the two current ranges. */ | ||
54 | |||
55 | /* If a bit is set, the corresponding DAC (4 ports each) is | ||
56 | not set at the moment you write to an output of it. | ||
57 | Clearing the bit updates the port. */ | ||
58 | #define ME1600_SIM_OUTPUT_REG 0x24 /**< Register to update all channels of a subdevice simultaneously. */ | ||
59 | |||
60 | /* Current on/off (only lower 8 bits): off = 0, on = 1 */ | ||
61 | #define ME1600_CURRENT_ON_REG 0x26 /**< Register to swicht between voltage and current output. */ | ||
62 | |||
63 | #define ME1600_AO_MAX_DATA 0x0FFF /**< The maximum digital data accepted by an analog output channel. */ | ||
64 | |||
65 | #endif | ||
66 | #endif | ||
diff --git a/drivers/staging/meilhaus/me1600_device.c b/drivers/staging/meilhaus/me1600_device.c deleted file mode 100644 index c244e984049e..000000000000 --- a/drivers/staging/meilhaus/me1600_device.c +++ /dev/null | |||
@@ -1,259 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1600_device.c | ||
3 | * | ||
4 | * @brief ME-1600 device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include "meids.h" | ||
42 | #include "meerror.h" | ||
43 | #include "mecommon.h" | ||
44 | #include "meinternal.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "medevice.h" | ||
48 | #include "mesubdevice.h" | ||
49 | #include "me1600_device.h" | ||
50 | |||
51 | static void me1600_set_registry(me1600_device_t *subdevice, uint32_t reg_base); | ||
52 | static void me1600_destructor(struct me_device *device); | ||
53 | |||
54 | /** | ||
55 | * @brief Global variable. | ||
56 | * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts). | ||
57 | */ | ||
58 | static struct workqueue_struct *me1600_workqueue; | ||
59 | |||
60 | me_device_t *me1600_pci_constructor(struct pci_dev *pci_device) | ||
61 | { | ||
62 | int err; | ||
63 | me1600_device_t *me1600_device; | ||
64 | me_subdevice_t *subdevice; | ||
65 | unsigned int chip_idx; | ||
66 | int i; | ||
67 | |||
68 | PDEBUG("executed.\n"); | ||
69 | |||
70 | // Allocate structure for device instance. | ||
71 | me1600_device = kmalloc(sizeof(me1600_device_t), GFP_KERNEL); | ||
72 | |||
73 | if (!me1600_device) { | ||
74 | PERROR("Cannot get memory for device instance.\n"); | ||
75 | return NULL; | ||
76 | } | ||
77 | |||
78 | memset(me1600_device, 0, sizeof(me1600_device_t)); | ||
79 | |||
80 | // Initialize base class structure. | ||
81 | err = me_device_pci_init((me_device_t *) me1600_device, pci_device); | ||
82 | |||
83 | if (err) { | ||
84 | kfree(me1600_device); | ||
85 | PERROR("Cannot initialize device base class.\n"); | ||
86 | return NULL; | ||
87 | } | ||
88 | // Initialize spin lock . | ||
89 | spin_lock_init(&me1600_device->config_regs_lock); | ||
90 | spin_lock_init(&me1600_device->ao_shadows_lock); | ||
91 | |||
92 | // Get the number of analog output subdevices. | ||
93 | chip_idx = | ||
94 | me1600_versions_get_device_index(me1600_device->base.info.pci. | ||
95 | device_id); | ||
96 | |||
97 | // Create shadow instance. | ||
98 | me1600_device->ao_regs_shadows.count = | ||
99 | me1600_versions[chip_idx].ao_chips; | ||
100 | me1600_device->ao_regs_shadows.registry = | ||
101 | kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(unsigned long), | ||
102 | GFP_KERNEL); | ||
103 | me1600_set_registry(me1600_device, | ||
104 | me1600_device->base.info.pci.reg_bases[2]); | ||
105 | me1600_device->ao_regs_shadows.shadow = | ||
106 | kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(uint16_t), | ||
107 | GFP_KERNEL); | ||
108 | me1600_device->ao_regs_shadows.mirror = | ||
109 | kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(uint16_t), | ||
110 | GFP_KERNEL); | ||
111 | |||
112 | // Create subdevice instances. | ||
113 | for (i = 0; i < me1600_versions[chip_idx].ao_chips; i++) { | ||
114 | subdevice = | ||
115 | (me_subdevice_t *) me1600_ao_constructor(me1600_device-> | ||
116 | base.info.pci. | ||
117 | reg_bases[2], i, | ||
118 | ((me1600_versions | ||
119 | [chip_idx].curr > | ||
120 | i) ? 1 : 0), | ||
121 | &me1600_device-> | ||
122 | config_regs_lock, | ||
123 | &me1600_device-> | ||
124 | ao_shadows_lock, | ||
125 | &me1600_device-> | ||
126 | ao_regs_shadows, | ||
127 | me1600_workqueue); | ||
128 | |||
129 | if (!subdevice) { | ||
130 | me_device_deinit((me_device_t *) me1600_device); | ||
131 | kfree(me1600_device); | ||
132 | PERROR("Cannot get memory for subdevice.\n"); | ||
133 | return NULL; | ||
134 | } | ||
135 | |||
136 | me_slist_add_subdevice_tail(&me1600_device->base.slist, | ||
137 | subdevice); | ||
138 | } | ||
139 | |||
140 | // Overwrite base class methods. | ||
141 | me1600_device->base.me_device_destructor = me1600_destructor; | ||
142 | |||
143 | return (me_device_t *) me1600_device; | ||
144 | } | ||
145 | EXPORT_SYMBOL(me1600_pci_constructor); | ||
146 | |||
147 | static void me1600_destructor(struct me_device *device) | ||
148 | { | ||
149 | me1600_device_t *me1600_device = (me1600_device_t *) device; | ||
150 | PDEBUG("executed.\n"); | ||
151 | |||
152 | // Destroy shadow instance. | ||
153 | kfree(me1600_device->ao_regs_shadows.registry); | ||
154 | kfree(me1600_device->ao_regs_shadows.shadow); | ||
155 | kfree(me1600_device->ao_regs_shadows.mirror); | ||
156 | |||
157 | me_device_deinit((me_device_t *) me1600_device); | ||
158 | kfree(me1600_device); | ||
159 | } | ||
160 | |||
161 | static void me1600_set_registry(me1600_device_t *subdevice, uint32_t reg_base) | ||
162 | { // Create shadow structure. | ||
163 | if (subdevice->ao_regs_shadows.count >= 1) { | ||
164 | subdevice->ao_regs_shadows.registry[0] = | ||
165 | (unsigned long)(reg_base + ME1600_CHANNEL_0_REG); | ||
166 | } | ||
167 | if (subdevice->ao_regs_shadows.count >= 2) { | ||
168 | subdevice->ao_regs_shadows.registry[1] = | ||
169 | (unsigned long)(reg_base + ME1600_CHANNEL_1_REG); | ||
170 | } | ||
171 | if (subdevice->ao_regs_shadows.count >= 3) { | ||
172 | subdevice->ao_regs_shadows.registry[2] = | ||
173 | (unsigned long)(reg_base + ME1600_CHANNEL_2_REG); | ||
174 | } | ||
175 | if (subdevice->ao_regs_shadows.count >= 4) { | ||
176 | subdevice->ao_regs_shadows.registry[3] = | ||
177 | (unsigned long)(reg_base + ME1600_CHANNEL_3_REG); | ||
178 | } | ||
179 | if (subdevice->ao_regs_shadows.count >= 5) { | ||
180 | subdevice->ao_regs_shadows.registry[4] = | ||
181 | (unsigned long)(reg_base + ME1600_CHANNEL_4_REG); | ||
182 | } | ||
183 | if (subdevice->ao_regs_shadows.count >= 6) { | ||
184 | subdevice->ao_regs_shadows.registry[5] = | ||
185 | (unsigned long)(reg_base + ME1600_CHANNEL_5_REG); | ||
186 | } | ||
187 | if (subdevice->ao_regs_shadows.count >= 7) { | ||
188 | subdevice->ao_regs_shadows.registry[6] = | ||
189 | (unsigned long)(reg_base + ME1600_CHANNEL_6_REG); | ||
190 | } | ||
191 | if (subdevice->ao_regs_shadows.count >= 8) { | ||
192 | subdevice->ao_regs_shadows.registry[7] = | ||
193 | (unsigned long)(reg_base + ME1600_CHANNEL_7_REG); | ||
194 | } | ||
195 | if (subdevice->ao_regs_shadows.count >= 9) { | ||
196 | subdevice->ao_regs_shadows.registry[8] = | ||
197 | (unsigned long)(reg_base + ME1600_CHANNEL_8_REG); | ||
198 | } | ||
199 | if (subdevice->ao_regs_shadows.count >= 10) { | ||
200 | subdevice->ao_regs_shadows.registry[9] = | ||
201 | (unsigned long)(reg_base + ME1600_CHANNEL_9_REG); | ||
202 | } | ||
203 | if (subdevice->ao_regs_shadows.count >= 11) { | ||
204 | subdevice->ao_regs_shadows.registry[10] = | ||
205 | (unsigned long)(reg_base + ME1600_CHANNEL_10_REG); | ||
206 | } | ||
207 | if (subdevice->ao_regs_shadows.count >= 12) { | ||
208 | subdevice->ao_regs_shadows.registry[11] = | ||
209 | (unsigned long)(reg_base + ME1600_CHANNEL_11_REG); | ||
210 | } | ||
211 | if (subdevice->ao_regs_shadows.count >= 13) { | ||
212 | subdevice->ao_regs_shadows.registry[12] = | ||
213 | (unsigned long)(reg_base + ME1600_CHANNEL_12_REG); | ||
214 | } | ||
215 | if (subdevice->ao_regs_shadows.count >= 14) { | ||
216 | subdevice->ao_regs_shadows.registry[13] = | ||
217 | (unsigned long)(reg_base + ME1600_CHANNEL_13_REG); | ||
218 | } | ||
219 | if (subdevice->ao_regs_shadows.count >= 15) { | ||
220 | subdevice->ao_regs_shadows.registry[14] = | ||
221 | (unsigned long)(reg_base + ME1600_CHANNEL_14_REG); | ||
222 | } | ||
223 | if (subdevice->ao_regs_shadows.count >= 16) { | ||
224 | subdevice->ao_regs_shadows.registry[15] = | ||
225 | (unsigned long)(reg_base + ME1600_CHANNEL_15_REG); | ||
226 | } | ||
227 | if (subdevice->ao_regs_shadows.count > 16) { | ||
228 | PERROR("More than 16 outputs! (%d)\n", | ||
229 | subdevice->ao_regs_shadows.count); | ||
230 | } | ||
231 | } | ||
232 | |||
233 | // Init and exit of module. | ||
234 | |||
235 | static int __init me1600_init(void) | ||
236 | { | ||
237 | PDEBUG("executed\n."); | ||
238 | |||
239 | me1600_workqueue = create_singlethread_workqueue("me1600"); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static void __exit me1600_exit(void) | ||
244 | { | ||
245 | PDEBUG("executed\n."); | ||
246 | |||
247 | flush_workqueue(me1600_workqueue); | ||
248 | destroy_workqueue(me1600_workqueue); | ||
249 | } | ||
250 | |||
251 | module_init(me1600_init); | ||
252 | module_exit(me1600_exit); | ||
253 | |||
254 | // Administrative stuff for modinfo. | ||
255 | MODULE_AUTHOR | ||
256 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
257 | MODULE_DESCRIPTION("Device Driver Module for ME-1600 Device"); | ||
258 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-1600 Devices"); | ||
259 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me1600_device.h b/drivers/staging/meilhaus/me1600_device.h deleted file mode 100644 index c73aca11ae88..000000000000 --- a/drivers/staging/meilhaus/me1600_device.h +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | /** | ||
2 | * @file me1600_device.h | ||
3 | * | ||
4 | * @brief ME-1600 device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME1600_H | ||
28 | #define _ME1600_H | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | #include "me1600_ao.h" | ||
35 | #include "me1600_ao_reg.h" | ||
36 | |||
37 | #ifdef __KERNEL__ | ||
38 | |||
39 | /** | ||
40 | * @brief Structure to store device capabilities. | ||
41 | */ | ||
42 | typedef struct me1600_version { | ||
43 | uint16_t device_id; /**< The PCI device id of the device. */ | ||
44 | unsigned int ao_chips; /**< The number of analog outputs on the device. */ | ||
45 | int curr; /**< Flag to identify amounts of current output. */ | ||
46 | } me1600_version_t; | ||
47 | |||
48 | /** | ||
49 | * @brief Defines for each ME-1600 device version its capabilities. | ||
50 | */ | ||
51 | static me1600_version_t me1600_versions[] = { | ||
52 | {PCI_DEVICE_ID_MEILHAUS_ME1600_4U, 4, 0}, | ||
53 | {PCI_DEVICE_ID_MEILHAUS_ME1600_8U, 8, 0}, | ||
54 | {PCI_DEVICE_ID_MEILHAUS_ME1600_12U, 12, 0}, | ||
55 | {PCI_DEVICE_ID_MEILHAUS_ME1600_16U, 16, 0}, | ||
56 | {PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I, 16, 8}, | ||
57 | {0} | ||
58 | }; | ||
59 | |||
60 | /**< Returns the number of entries in #me1600_versions. */ | ||
61 | #define ME1600_DEVICE_VERSIONS (ARRAY_SIZE(me1600_versions) - 1) | ||
62 | |||
63 | /** | ||
64 | * @brief Returns the index of the device entry in #me1600_versions. | ||
65 | * | ||
66 | * @param device_id The PCI device id of the device to query. | ||
67 | * @return The index of the device in #me1600_versions. | ||
68 | */ | ||
69 | static inline unsigned int me1600_versions_get_device_index(uint16_t device_id) | ||
70 | { | ||
71 | unsigned int i; | ||
72 | for (i = 0; i < ME1600_DEVICE_VERSIONS; i++) | ||
73 | if (me1600_versions[i].device_id == device_id) | ||
74 | break; | ||
75 | return i; | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * @brief The ME-1600 device class structure. | ||
80 | */ | ||
81 | typedef struct me1600_device { | ||
82 | me_device_t base; /**< The Meilhaus device base class. */ | ||
83 | spinlock_t config_regs_lock; /**< Protects the configuration registers. */ | ||
84 | |||
85 | me1600_ao_shadow_t ao_regs_shadows; /**< Addresses and shadows of output's registers. */ | ||
86 | spinlock_t ao_shadows_lock; /**< Protects the shadow's struct. */ | ||
87 | } me1600_device_t; | ||
88 | |||
89 | /** | ||
90 | * @brief The ME-1600 device class constructor. | ||
91 | * | ||
92 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
93 | * | ||
94 | * @return On succes a new ME-1600 device instance. \n | ||
95 | * NULL on error. | ||
96 | */ | ||
97 | me_device_t *me1600_pci_constructor(struct pci_dev *pci_device) | ||
98 | __attribute__ ((weak)); | ||
99 | |||
100 | #endif | ||
101 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_ai.c b/drivers/staging/meilhaus/me4600_ai.c deleted file mode 100644 index fd9daa942fb3..000000000000 --- a/drivers/staging/meilhaus/me4600_ai.c +++ /dev/null | |||
@@ -1,3405 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ai.c | ||
3 | * | ||
4 | * @brief ME-4000 analog input subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/uaccess.h> | ||
41 | #include <linux/types.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/delay.h> | ||
44 | |||
45 | #include "medefines.h" | ||
46 | #include "meinternal.h" | ||
47 | #include "meerror.h" | ||
48 | #include "medebug.h" | ||
49 | #include "meids.h" | ||
50 | |||
51 | #include "me4600_reg.h" | ||
52 | #include "me4600_ai_reg.h" | ||
53 | #include "me4600_ai.h" | ||
54 | |||
55 | /* | ||
56 | * Declarations (local) | ||
57 | */ | ||
58 | |||
59 | static void me4600_ai_destructor(struct me_subdevice *subdevice); | ||
60 | static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, | ||
61 | struct file *filep, int flags); | ||
62 | |||
63 | static int me4600_ai_io_single_config(me_subdevice_t *subdevice, | ||
64 | struct file *filep, | ||
65 | int channel, | ||
66 | int single_config, | ||
67 | int ref, | ||
68 | int trig_chan, | ||
69 | int trig_type, int trig_edge, int flags); | ||
70 | |||
71 | static int me4600_ai_io_single_read(me_subdevice_t *subdevice, | ||
72 | struct file *filep, | ||
73 | int channel, | ||
74 | int *value, int time_out, int flags); | ||
75 | |||
76 | static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, | ||
77 | struct file *filep, | ||
78 | meIOStreamConfig_t *config_list, | ||
79 | int count, | ||
80 | meIOStreamTrigger_t *trigger, | ||
81 | int fifo_irq_threshold, int flags); | ||
82 | static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, | ||
83 | struct file *filep, | ||
84 | int read_mode, | ||
85 | int *values, int *count, int flags); | ||
86 | static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, | ||
87 | struct file *filep, | ||
88 | int time_out, int *count, int flags); | ||
89 | static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * | ||
90 | instance, int *values, | ||
91 | const int count, | ||
92 | const int flags); | ||
93 | |||
94 | static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, | ||
95 | struct file *filep, | ||
96 | int start_mode, int time_out, int flags); | ||
97 | static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, | ||
98 | struct file *filep, | ||
99 | int stop_mode, int flags); | ||
100 | static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, | ||
101 | struct file *filep, | ||
102 | int wait, | ||
103 | int *status, int *values, int flags); | ||
104 | |||
105 | static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, | ||
106 | int unit, | ||
107 | int *min, | ||
108 | int *max, int *maxdata, int *range); | ||
109 | static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, | ||
110 | int unit, int *count); | ||
111 | static int me4600_ai_query_range_info(me_subdevice_t *subdevice, | ||
112 | int range, | ||
113 | int *unit, | ||
114 | int *min, int *max, int *maxdata); | ||
115 | static int me4600_ai_query_timer(me_subdevice_t *subdevice, | ||
116 | int timer, | ||
117 | int *base_frequency, | ||
118 | long long *min_ticks, long long *max_ticks); | ||
119 | static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, | ||
120 | int *number); | ||
121 | static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, | ||
122 | int *type, int *subtype); | ||
123 | static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, | ||
124 | int *caps); | ||
125 | static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, | ||
126 | int cap, int *args, int count); | ||
127 | |||
128 | static irqreturn_t me4600_ai_isr(int irq, void *dev_id); | ||
129 | |||
130 | static int ai_mux_toggler(me4600_ai_subdevice_t *subdevice); | ||
131 | |||
132 | /** Immidiate stop. | ||
133 | * Reset all IRQ's sources. (block laches) | ||
134 | * Preserve FIFO | ||
135 | */ | ||
136 | static int ai_stop_immediately(me4600_ai_subdevice_t *instance); | ||
137 | |||
138 | /** Immidiate stop. | ||
139 | * Reset all IRQ's sources. (block laches) | ||
140 | * Reset data FIFO | ||
141 | */ | ||
142 | inline void ai_stop_isr(me4600_ai_subdevice_t *instance); | ||
143 | |||
144 | /** Interrupt logics. | ||
145 | * Read datas | ||
146 | * Reset latches | ||
147 | */ | ||
148 | void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, | ||
149 | const uint32_t ctrl_status); | ||
150 | void ai_infinite_isr(me4600_ai_subdevice_t *instance, | ||
151 | const uint32_t irq_status, const uint32_t ctrl_status); | ||
152 | |||
153 | /** Last chunck of datas. We must reschedule sample counter. | ||
154 | * Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. | ||
155 | * When threshold is wrongly set some IRQ are lost.(!!!) | ||
156 | */ | ||
157 | inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance); | ||
158 | |||
159 | /** Read datas from FIFO and copy them to buffer */ | ||
160 | static inline int ai_read_data(me4600_ai_subdevice_t *instance, | ||
161 | const int count); | ||
162 | |||
163 | /** Copy rest of data from fifo to circular buffer.*/ | ||
164 | static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance); | ||
165 | |||
166 | /** Set ISM to next state for infinite data aqusation mode*/ | ||
167 | inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance); | ||
168 | |||
169 | /** Set ISM to next state for define amount of data aqusation mode*/ | ||
170 | inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, | ||
171 | uint32_t irq_status); | ||
172 | |||
173 | /** Set ISM to next stage for limited mode */ | ||
174 | inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance); | ||
175 | |||
176 | static void me4600_ai_work_control_task(struct work_struct *work); | ||
177 | |||
178 | /* Definitions | ||
179 | */ | ||
180 | |||
181 | me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base, | ||
182 | unsigned int channels, | ||
183 | unsigned int ranges, | ||
184 | int isolated, | ||
185 | int sh, | ||
186 | int irq, | ||
187 | spinlock_t *ctrl_reg_lock, | ||
188 | struct workqueue_struct *me4600_wq) | ||
189 | { | ||
190 | me4600_ai_subdevice_t *subdevice; | ||
191 | int err; | ||
192 | unsigned int i; | ||
193 | |||
194 | PDEBUG("executed. idx=0\n"); | ||
195 | |||
196 | // Allocate memory for subdevice instance. | ||
197 | subdevice = kmalloc(sizeof(me4600_ai_subdevice_t), GFP_KERNEL); | ||
198 | |||
199 | if (!subdevice) { | ||
200 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
201 | return NULL; | ||
202 | } | ||
203 | |||
204 | memset(subdevice, 0, sizeof(me4600_ai_subdevice_t)); | ||
205 | |||
206 | // Initialize subdevice base class. | ||
207 | err = me_subdevice_init(&subdevice->base); | ||
208 | |||
209 | if (err) { | ||
210 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
211 | kfree(subdevice); | ||
212 | return NULL; | ||
213 | } | ||
214 | // Initialize spin locks. | ||
215 | spin_lock_init(&subdevice->subdevice_lock); | ||
216 | |||
217 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
218 | |||
219 | // Initialize circular buffer. | ||
220 | subdevice->circ_buf.mask = ME4600_AI_CIRC_BUF_COUNT - 1; | ||
221 | |||
222 | subdevice->circ_buf.buf = | ||
223 | (void *)__get_free_pages(GFP_KERNEL, ME4600_AI_CIRC_BUF_SIZE_ORDER); | ||
224 | PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf, | ||
225 | ME4600_AI_CIRC_BUF_SIZE); | ||
226 | |||
227 | if (!subdevice->circ_buf.buf) { | ||
228 | PERROR("Cannot get circular buffer.\n"); | ||
229 | me_subdevice_deinit((me_subdevice_t *) subdevice); | ||
230 | kfree(subdevice); | ||
231 | return NULL; | ||
232 | } | ||
233 | |||
234 | memset(subdevice->circ_buf.buf, 0, ME4600_AI_CIRC_BUF_SIZE); | ||
235 | subdevice->circ_buf.head = 0; | ||
236 | subdevice->circ_buf.tail = 0; | ||
237 | subdevice->status = ai_status_none; | ||
238 | |||
239 | // Initialize wait queue. | ||
240 | init_waitqueue_head(&subdevice->wait_queue); | ||
241 | |||
242 | // Save the number of channels. | ||
243 | subdevice->channels = channels; | ||
244 | |||
245 | /* Initialize the single config entries to reset values */ | ||
246 | for (i = 0; i < channels; i++) { | ||
247 | subdevice->single_config[i].status = ME_SINGLE_CHANNEL_NOT_CONFIGURED; //not configured | ||
248 | } | ||
249 | |||
250 | // Save if isolated device. | ||
251 | subdevice->isolated = isolated; | ||
252 | |||
253 | // Save if sample and hold is available. | ||
254 | subdevice->sh = sh; | ||
255 | |||
256 | // Set stream config to not configured state. | ||
257 | subdevice->fifo_irq_threshold = 0; | ||
258 | subdevice->data_required = 0; | ||
259 | subdevice->chan_list_len = 0; | ||
260 | |||
261 | // Initialize registers addresses. | ||
262 | subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG; | ||
263 | subdevice->status_reg = reg_base + ME4600_AI_STATUS_REG; | ||
264 | subdevice->channel_list_reg = reg_base + ME4600_AI_CHANNEL_LIST_REG; | ||
265 | subdevice->data_reg = reg_base + ME4600_AI_DATA_REG; | ||
266 | subdevice->chan_timer_reg = reg_base + ME4600_AI_CHAN_TIMER_REG; | ||
267 | subdevice->chan_pre_timer_reg = reg_base + ME4600_AI_CHAN_PRE_TIMER_REG; | ||
268 | subdevice->scan_timer_low_reg = reg_base + ME4600_AI_SCAN_TIMER_LOW_REG; | ||
269 | subdevice->scan_timer_high_reg = | ||
270 | reg_base + ME4600_AI_SCAN_TIMER_HIGH_REG; | ||
271 | subdevice->scan_pre_timer_low_reg = | ||
272 | reg_base + ME4600_AI_SCAN_PRE_TIMER_LOW_REG; | ||
273 | subdevice->scan_pre_timer_high_reg = | ||
274 | reg_base + ME4600_AI_SCAN_PRE_TIMER_HIGH_REG; | ||
275 | subdevice->start_reg = reg_base + ME4600_AI_START_REG; | ||
276 | subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; | ||
277 | subdevice->sample_counter_reg = reg_base + ME4600_AI_SAMPLE_COUNTER_REG; | ||
278 | #ifdef MEDEBUG_DEBUG_REG | ||
279 | subdevice->reg_base = reg_base; | ||
280 | #endif | ||
281 | |||
282 | // Initialize ranges. | ||
283 | subdevice->ranges_len = ranges; | ||
284 | subdevice->ranges[0].min = -10E6; | ||
285 | subdevice->ranges[0].max = 9999694; | ||
286 | |||
287 | subdevice->ranges[1].min = 0; | ||
288 | subdevice->ranges[1].max = 9999847; | ||
289 | |||
290 | subdevice->ranges[2].min = -25E5; | ||
291 | subdevice->ranges[2].max = 2499923; | ||
292 | |||
293 | subdevice->ranges[3].min = 0; | ||
294 | subdevice->ranges[3].max = 2499961; | ||
295 | |||
296 | // We have to switch the mux in order to get it work correctly. | ||
297 | ai_mux_toggler(subdevice); | ||
298 | |||
299 | // Register interrupt service routine. | ||
300 | subdevice->irq = irq; | ||
301 | if (request_irq(subdevice->irq, me4600_ai_isr, | ||
302 | IRQF_DISABLED | IRQF_SHARED, | ||
303 | ME4600_NAME, subdevice)) { | ||
304 | PERROR("Cannot register interrupt service routine.\n"); | ||
305 | me_subdevice_deinit((me_subdevice_t *) subdevice); | ||
306 | free_pages((unsigned long)subdevice->circ_buf.buf, | ||
307 | ME4600_AI_CIRC_BUF_SIZE_ORDER); | ||
308 | subdevice->circ_buf.buf = NULL; | ||
309 | kfree(subdevice); | ||
310 | return NULL; | ||
311 | } | ||
312 | PINFO("Registered irq=%d.\n", subdevice->irq); | ||
313 | |||
314 | // Override base class methods. | ||
315 | subdevice->base.me_subdevice_destructor = me4600_ai_destructor; | ||
316 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
317 | me4600_ai_io_reset_subdevice; | ||
318 | subdevice->base.me_subdevice_io_single_config = | ||
319 | me4600_ai_io_single_config; | ||
320 | subdevice->base.me_subdevice_io_single_read = me4600_ai_io_single_read; | ||
321 | subdevice->base.me_subdevice_io_stream_config = | ||
322 | me4600_ai_io_stream_config; | ||
323 | subdevice->base.me_subdevice_io_stream_new_values = | ||
324 | me4600_ai_io_stream_new_values; | ||
325 | subdevice->base.me_subdevice_io_stream_read = me4600_ai_io_stream_read; | ||
326 | subdevice->base.me_subdevice_io_stream_start = | ||
327 | me4600_ai_io_stream_start; | ||
328 | subdevice->base.me_subdevice_io_stream_status = | ||
329 | me4600_ai_io_stream_status; | ||
330 | subdevice->base.me_subdevice_io_stream_stop = me4600_ai_io_stream_stop; | ||
331 | subdevice->base.me_subdevice_query_number_channels = | ||
332 | me4600_ai_query_number_channels; | ||
333 | subdevice->base.me_subdevice_query_subdevice_type = | ||
334 | me4600_ai_query_subdevice_type; | ||
335 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
336 | me4600_ai_query_subdevice_caps; | ||
337 | subdevice->base.me_subdevice_query_subdevice_caps_args = | ||
338 | me4600_ai_query_subdevice_caps_args; | ||
339 | subdevice->base.me_subdevice_query_range_by_min_max = | ||
340 | me4600_ai_query_range_by_min_max; | ||
341 | subdevice->base.me_subdevice_query_number_ranges = | ||
342 | me4600_ai_query_number_ranges; | ||
343 | subdevice->base.me_subdevice_query_range_info = | ||
344 | me4600_ai_query_range_info; | ||
345 | subdevice->base.me_subdevice_query_timer = me4600_ai_query_timer; | ||
346 | |||
347 | // Prepare work queue. | ||
348 | subdevice->me4600_workqueue = me4600_wq; | ||
349 | |||
350 | /* workqueue API changed in kernel 2.6.20 */ | ||
351 | INIT_DELAYED_WORK(&subdevice->ai_control_task, | ||
352 | me4600_ai_work_control_task); | ||
353 | |||
354 | return subdevice; | ||
355 | } | ||
356 | |||
357 | static void me4600_ai_destructor(struct me_subdevice *subdevice) | ||
358 | { | ||
359 | me4600_ai_subdevice_t *instance; | ||
360 | |||
361 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
362 | |||
363 | PDEBUG("executed. idx=0\n"); | ||
364 | |||
365 | instance->ai_control_task_flag = 0; | ||
366 | // Reset subdevice to asure clean exit. | ||
367 | me4600_ai_io_reset_subdevice(subdevice, NULL, | ||
368 | ME_IO_RESET_SUBDEVICE_NO_FLAGS); | ||
369 | |||
370 | // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). | ||
371 | if (!cancel_delayed_work(&instance->ai_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. | ||
372 | set_current_state(TASK_INTERRUPTIBLE); | ||
373 | schedule_timeout(2); | ||
374 | } | ||
375 | |||
376 | free_irq(instance->irq, instance); | ||
377 | free_pages((unsigned long)instance->circ_buf.buf, | ||
378 | ME4600_AI_CIRC_BUF_SIZE_ORDER); | ||
379 | me_subdevice_deinit(&instance->base); | ||
380 | kfree(instance); | ||
381 | } | ||
382 | |||
383 | static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, | ||
384 | struct file *filep, int flags) | ||
385 | { | ||
386 | me4600_ai_subdevice_t *instance; | ||
387 | int err = ME_ERRNO_SUCCESS; | ||
388 | volatile uint32_t ctrl; | ||
389 | unsigned long status; | ||
390 | const int timeout = HZ / 10; //100ms | ||
391 | int i; | ||
392 | |||
393 | PDEBUG("executed. idx=0\n"); | ||
394 | |||
395 | if (flags) { | ||
396 | PERROR("Invalid flag specified.\n"); | ||
397 | return ME_ERRNO_INVALID_FLAGS; | ||
398 | } | ||
399 | |||
400 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
401 | |||
402 | ME_SUBDEVICE_ENTER; | ||
403 | |||
404 | instance->ai_control_task_flag = 0; | ||
405 | instance->status = ai_status_none; | ||
406 | |||
407 | for (i = 0; i <= timeout; i++) { | ||
408 | spin_lock_irqsave(instance->ctrl_reg_lock, status); | ||
409 | ctrl = inl(instance->ctrl_reg); | ||
410 | //Stop DMA | ||
411 | ctrl &= ~ME4600_AI_CTRL_RPCI_FIFO; | ||
412 | // Stop all actions. No conditions! | ||
413 | ctrl &= ~ME4600_AI_CTRL_BIT_STOP; | ||
414 | ctrl |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
415 | |||
416 | outl(ctrl, instance->ctrl_reg); | ||
417 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
418 | instance->reg_base, | ||
419 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
420 | spin_unlock_irqrestore(instance->ctrl_reg_lock, status); | ||
421 | |||
422 | if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) | ||
423 | break; | ||
424 | |||
425 | set_current_state(TASK_INTERRUPTIBLE); | ||
426 | schedule_timeout(1); | ||
427 | } | ||
428 | |||
429 | if (i > timeout) { | ||
430 | PERROR("FSM is still busy.\n"); | ||
431 | ME_SUBDEVICE_EXIT; | ||
432 | return ME_ERRNO_INTERNAL; | ||
433 | } | ||
434 | |||
435 | spin_lock_irqsave(instance->ctrl_reg_lock, status); | ||
436 | ctrl = inl(instance->ctrl_reg); | ||
437 | // Clear all features. Dissable interrupts. | ||
438 | ctrl &= ~(ME4600_AI_CTRL_BIT_STOP | ||
439 | | ME4600_AI_CTRL_BIT_LE_IRQ | ||
440 | | ME4600_AI_CTRL_BIT_HF_IRQ | ME4600_AI_CTRL_BIT_SC_IRQ); | ||
441 | ctrl |= (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ||
442 | | ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ||
443 | | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | ||
444 | | ME4600_AI_CTRL_BIT_SC_IRQ_RESET); | ||
445 | |||
446 | outl(ctrl, instance->ctrl_reg); | ||
447 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
448 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
449 | spin_unlock_irqrestore(instance->ctrl_reg_lock, status); | ||
450 | |||
451 | outl(ME4600_AI_MIN_CHAN_TICKS - 1, instance->chan_timer_reg); | ||
452 | PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llx\n", | ||
453 | instance->reg_base, | ||
454 | instance->chan_timer_reg - instance->reg_base, | ||
455 | ME4600_AI_MIN_CHAN_TICKS); | ||
456 | outl(ME4600_AI_MIN_ACQ_TICKS - 1, instance->chan_pre_timer_reg); | ||
457 | PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llx\n", | ||
458 | instance->reg_base, | ||
459 | instance->chan_pre_timer_reg - instance->reg_base, | ||
460 | ME4600_AI_MIN_ACQ_TICKS); | ||
461 | outl(0, instance->scan_timer_low_reg); | ||
462 | PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
463 | instance->reg_base, | ||
464 | instance->scan_timer_low_reg - instance->reg_base, 0); | ||
465 | outl(0, instance->scan_timer_high_reg); | ||
466 | PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
467 | instance->reg_base, | ||
468 | instance->scan_timer_high_reg - instance->reg_base, 0); | ||
469 | outl(0, instance->scan_pre_timer_low_reg); | ||
470 | PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
471 | instance->reg_base, | ||
472 | instance->scan_pre_timer_low_reg - instance->reg_base, 0); | ||
473 | outl(0, instance->scan_pre_timer_high_reg); | ||
474 | PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
475 | instance->reg_base, | ||
476 | instance->scan_pre_timer_high_reg - instance->reg_base, 0); | ||
477 | outl(0xEFFFFFFF, instance->sample_counter_reg); | ||
478 | PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
479 | instance->reg_base, | ||
480 | instance->sample_counter_reg - instance->reg_base, | ||
481 | 0xEFFFFFFF); | ||
482 | |||
483 | instance->circ_buf.head = 0; | ||
484 | instance->circ_buf.tail = 0; | ||
485 | |||
486 | instance->fifo_irq_threshold = 0; | ||
487 | instance->data_required = 0; | ||
488 | instance->chan_list_len = 0; | ||
489 | |||
490 | // Initialize the single config entries to reset values. | ||
491 | for (i = 0; i < instance->channels; i++) { | ||
492 | instance->single_config[i].status = | ||
493 | ME_SINGLE_CHANNEL_NOT_CONFIGURED; | ||
494 | } | ||
495 | instance->status = ai_status_none; | ||
496 | |||
497 | //Signal reset if user is on wait. | ||
498 | wake_up_interruptible_all(&instance->wait_queue); | ||
499 | |||
500 | ME_SUBDEVICE_EXIT; | ||
501 | |||
502 | return err; | ||
503 | } | ||
504 | |||
505 | static int me4600_ai_io_single_config(me_subdevice_t *subdevice, | ||
506 | struct file *filep, | ||
507 | int channel, | ||
508 | int single_config, | ||
509 | int ref, | ||
510 | int trig_chan, | ||
511 | int trig_type, int trig_edge, int flags) | ||
512 | { | ||
513 | me4600_ai_subdevice_t *instance; | ||
514 | int err = ME_ERRNO_SUCCESS; | ||
515 | unsigned long cpu_flags; | ||
516 | int i; | ||
517 | |||
518 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
519 | |||
520 | PDEBUG("executed. idx=0\n"); | ||
521 | |||
522 | if (flags & ~ME_IO_SINGLE_CONFIG_CONTINUE) { | ||
523 | PERROR("Invalid flag specified.\n"); | ||
524 | return ME_ERRNO_INVALID_FLAGS; | ||
525 | } | ||
526 | |||
527 | switch (trig_type) { | ||
528 | case ME_TRIG_TYPE_SW: | ||
529 | if (trig_edge != ME_TRIG_EDGE_NONE) { | ||
530 | PERROR | ||
531 | ("Invalid trigger edge. Software trigger has not edge.\n"); | ||
532 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
533 | } | ||
534 | break; | ||
535 | |||
536 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
537 | if (instance->channels <= 16) //Only versions with 32 channels have analog trigger (4670 and 4680) | ||
538 | { | ||
539 | PERROR("Invalid trigger type specified.\n"); | ||
540 | return ME_ERRNO_INVALID_TRIG_TYPE; | ||
541 | } | ||
542 | |||
543 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
544 | if ((trig_edge != ME_TRIG_EDGE_ANY) | ||
545 | && (trig_edge != ME_TRIG_EDGE_RISING) | ||
546 | && (trig_edge != ME_TRIG_EDGE_FALLING)) { | ||
547 | PERROR("Invalid trigger edge specified.\n"); | ||
548 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
549 | } | ||
550 | break; | ||
551 | |||
552 | default: | ||
553 | PERROR("Invalid trigger type specified.\n"); | ||
554 | return ME_ERRNO_INVALID_TRIG_TYPE; | ||
555 | } | ||
556 | |||
557 | if (trig_chan != ME_TRIG_CHAN_DEFAULT) { | ||
558 | PERROR("Invalid trigger channel specified.\n"); | ||
559 | return ME_ERRNO_INVALID_TRIG_CHAN; | ||
560 | } | ||
561 | |||
562 | if ((single_config < 0) || (single_config >= instance->ranges_len)) { | ||
563 | PERROR("Invalid single config specified.\n"); | ||
564 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
565 | } | ||
566 | |||
567 | if ((ref != ME_REF_AI_GROUND) && (ref != ME_REF_AI_DIFFERENTIAL)) { | ||
568 | PERROR("Invalid analog reference specified.\n"); | ||
569 | return ME_ERRNO_INVALID_REF; | ||
570 | } | ||
571 | |||
572 | if ((single_config % 2) && (ref != ME_REF_AI_GROUND)) { | ||
573 | PERROR("Invalid analog reference specified.\n"); | ||
574 | return ME_ERRNO_INVALID_REF; | ||
575 | } | ||
576 | |||
577 | if ((ref == ME_REF_AI_DIFFERENTIAL) | ||
578 | && ((instance->channels == 16) || (channel >= 16))) { | ||
579 | PERROR("Invalid analog reference specified.\n"); | ||
580 | return ME_ERRNO_INVALID_REF; | ||
581 | } | ||
582 | |||
583 | if (channel < 0) { | ||
584 | PERROR("Invalid channel number specified.\n"); | ||
585 | return ME_ERRNO_INVALID_CHANNEL; | ||
586 | } | ||
587 | |||
588 | if (channel >= instance->channels) { | ||
589 | PERROR("Invalid channel number specified.\n"); | ||
590 | return ME_ERRNO_INVALID_CHANNEL; | ||
591 | } | ||
592 | |||
593 | ME_SUBDEVICE_ENTER; | ||
594 | |||
595 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
596 | //Prepare data entry. | ||
597 | // Common for all modes. | ||
598 | instance->single_config[channel].entry = | ||
599 | channel | ME4600_AI_LIST_LAST_ENTRY; | ||
600 | |||
601 | if (ref == ME_REF_AI_DIFFERENTIAL) { // ME_REF_AI_DIFFERENTIAL | ||
602 | instance->single_config[channel].entry |= | ||
603 | ME4600_AI_LIST_INPUT_DIFFERENTIAL; | ||
604 | } | ||
605 | /* | ||
606 | // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000 | ||
607 | // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' <== Do nothing. Removed. | ||
608 | else | ||
609 | {// ME_REF_AI_GROUND | ||
610 | instance->single_config[channel].entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED; | ||
611 | } | ||
612 | */ | ||
613 | switch (single_config) { | ||
614 | case 0: //-10V..10V | ||
615 | /* | ||
616 | // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000 | ||
617 | // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed. | ||
618 | instance->single_config[channel].entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10; | ||
619 | */ break; | ||
620 | |||
621 | case 1: //0V..10V | ||
622 | instance->single_config[channel].entry |= | ||
623 | ME4600_AI_LIST_RANGE_UNIPOLAR_10; | ||
624 | break; | ||
625 | |||
626 | case 2: //-2.5V..2.5V | ||
627 | instance->single_config[channel].entry |= | ||
628 | ME4600_AI_LIST_RANGE_BIPOLAR_2_5; | ||
629 | break; | ||
630 | |||
631 | case 3: //0V..2.5V | ||
632 | instance->single_config[channel].entry |= | ||
633 | ME4600_AI_LIST_RANGE_UNIPOLAR_2_5; | ||
634 | break; | ||
635 | } | ||
636 | |||
637 | // Prepare control register. | ||
638 | // Common for all modes. | ||
639 | instance->single_config[channel].ctrl = | ||
640 | ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; | ||
641 | |||
642 | switch (trig_type) { | ||
643 | case ME_TRIG_TYPE_SW: | ||
644 | // Nothing to set. | ||
645 | break; | ||
646 | |||
647 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
648 | instance->single_config[channel].ctrl |= | ||
649 | ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG; | ||
650 | |||
651 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
652 | instance->single_config[channel].ctrl |= | ||
653 | ME4600_AI_CTRL_BIT_EX_TRIG; | ||
654 | break; | ||
655 | } | ||
656 | |||
657 | switch (trig_edge) { | ||
658 | case ME_TRIG_EDGE_RISING: | ||
659 | // Nothing to set. | ||
660 | break; | ||
661 | |||
662 | case ME_TRIG_EDGE_ANY: | ||
663 | instance->single_config[channel].ctrl |= | ||
664 | ME4600_AI_CTRL_BIT_EX_TRIG_BOTH; | ||
665 | |||
666 | case ME_TRIG_EDGE_FALLING: | ||
667 | instance->single_config[channel].ctrl |= | ||
668 | ME4600_AI_CTRL_BIT_EX_TRIG_FALLING; | ||
669 | break; | ||
670 | } | ||
671 | |||
672 | // Enable this channel | ||
673 | instance->single_config[channel].status = ME_SINGLE_CHANNEL_CONFIGURED; | ||
674 | |||
675 | // Copy this settings to other outputs. | ||
676 | if (flags == ME_IO_SINGLE_CONFIG_CONTINUE) { | ||
677 | for (i = channel + 1; i < instance->channels; i++) { | ||
678 | instance->single_config[i].ctrl = | ||
679 | instance->single_config[channel].ctrl; | ||
680 | instance->single_config[i].entry = | ||
681 | instance->single_config[channel].entry; | ||
682 | instance->single_config[i].status = | ||
683 | ME_SINGLE_CHANNEL_CONFIGURED; | ||
684 | } | ||
685 | } | ||
686 | |||
687 | instance->status = ai_status_single_configured; | ||
688 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
689 | |||
690 | ME_SUBDEVICE_EXIT; | ||
691 | |||
692 | return err; | ||
693 | } | ||
694 | |||
695 | static int me4600_ai_io_single_read(me_subdevice_t *subdevice, | ||
696 | struct file *filep, | ||
697 | int channel, | ||
698 | int *value, int time_out, int flags) | ||
699 | { | ||
700 | me4600_ai_subdevice_t *instance; | ||
701 | volatile uint32_t tmp; | ||
702 | volatile uint32_t val; | ||
703 | unsigned long cpu_flags; | ||
704 | int err = ME_ERRNO_SUCCESS; | ||
705 | |||
706 | unsigned long j; | ||
707 | unsigned long delay = 0; | ||
708 | |||
709 | PDEBUG("executed. idx=0\n"); | ||
710 | |||
711 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
712 | |||
713 | if (flags) { | ||
714 | PERROR("Invalid flag specified.\n"); | ||
715 | return ME_ERRNO_INVALID_FLAGS; | ||
716 | } | ||
717 | |||
718 | if (instance->status != ai_status_single_configured) { | ||
719 | PERROR("Subdevice not configured to work in single mode!\n"); | ||
720 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
721 | } | ||
722 | |||
723 | if ((channel > instance->channels) || (channel < 0)) { | ||
724 | PERROR("Invalid channel specified.\n"); | ||
725 | return ME_ERRNO_INVALID_CHANNEL; | ||
726 | } | ||
727 | |||
728 | if (time_out < 0) { | ||
729 | PERROR("Invalid timeout specified.\n"); | ||
730 | return ME_ERRNO_INVALID_TIMEOUT; | ||
731 | } | ||
732 | |||
733 | if (instance->single_config[channel].status != | ||
734 | ME_SINGLE_CHANNEL_CONFIGURED) { | ||
735 | PERROR("Channel is not configured to work in single mode!\n"); | ||
736 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
737 | } | ||
738 | |||
739 | if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) { | ||
740 | PERROR("Subdevice is busy.\n"); | ||
741 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
742 | } | ||
743 | |||
744 | ME_SUBDEVICE_ENTER; | ||
745 | |||
746 | // Cancel control task | ||
747 | PDEBUG("Cancel control task.\n"); | ||
748 | instance->ai_control_task_flag = 0; | ||
749 | cancel_delayed_work(&instance->ai_control_task); | ||
750 | |||
751 | if (time_out) { | ||
752 | delay = (time_out * HZ) / 1000; | ||
753 | |||
754 | if (delay == 0) | ||
755 | delay = 1; | ||
756 | } | ||
757 | |||
758 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
759 | |||
760 | // Mark that StreamConfig is removed. | ||
761 | instance->chan_list_len = 0; | ||
762 | |||
763 | spin_lock(instance->ctrl_reg_lock); | ||
764 | /// @note Imprtant: Preserve EXT IRQ settings. | ||
765 | tmp = inl(instance->ctrl_reg); | ||
766 | // Clear FIFOs and dissable interrupts | ||
767 | tmp &= | ||
768 | ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); | ||
769 | |||
770 | tmp &= | ||
771 | ~(ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ | | ||
772 | ME4600_AI_CTRL_BIT_LE_IRQ); | ||
773 | tmp |= | ||
774 | ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | | ||
775 | ME4600_AI_CTRL_BIT_LE_IRQ_RESET; | ||
776 | |||
777 | tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
778 | outl(tmp, instance->ctrl_reg); | ||
779 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
780 | instance->ctrl_reg - instance->reg_base, tmp); | ||
781 | |||
782 | outl(0, instance->scan_pre_timer_low_reg); | ||
783 | PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
784 | instance->reg_base, | ||
785 | instance->scan_pre_timer_low_reg - instance->reg_base, 0); | ||
786 | outl(0, instance->scan_pre_timer_high_reg); | ||
787 | PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
788 | instance->reg_base, | ||
789 | instance->scan_pre_timer_high_reg - instance->reg_base, 0); | ||
790 | outl(0, instance->scan_timer_low_reg); | ||
791 | PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
792 | instance->reg_base, | ||
793 | instance->scan_timer_low_reg - instance->reg_base, 0); | ||
794 | outl(0, instance->scan_timer_high_reg); | ||
795 | PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
796 | instance->reg_base, | ||
797 | instance->scan_timer_high_reg - instance->reg_base, 0); | ||
798 | outl(65, instance->chan_timer_reg); | ||
799 | PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
800 | instance->reg_base, | ||
801 | instance->chan_timer_reg - instance->reg_base, 65); | ||
802 | outl(65, instance->chan_pre_timer_reg); | ||
803 | PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
804 | instance->reg_base, | ||
805 | instance->chan_pre_timer_reg - instance->reg_base, 65); | ||
806 | |||
807 | //Reactive FIFOs. Enable work. | ||
808 | tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; | ||
809 | outl(tmp, instance->ctrl_reg); | ||
810 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
811 | instance->ctrl_reg - instance->reg_base, tmp); | ||
812 | |||
813 | outl(instance->single_config[channel].entry, | ||
814 | instance->channel_list_reg); | ||
815 | PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
816 | instance->reg_base, | ||
817 | instance->channel_list_reg - instance->reg_base, | ||
818 | instance->single_config[channel].entry); | ||
819 | |||
820 | // Preserve EXT IRQ settings. | ||
821 | tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); | ||
822 | outl(instance->single_config[channel].ctrl | tmp, instance->ctrl_reg); | ||
823 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
824 | instance->ctrl_reg - instance->reg_base, | ||
825 | instance->single_config[channel].ctrl | tmp); | ||
826 | |||
827 | spin_unlock(instance->ctrl_reg_lock); | ||
828 | |||
829 | if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start | ||
830 | inl(instance->start_reg); | ||
831 | PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, | ||
832 | instance->start_reg - instance->reg_base); | ||
833 | |||
834 | delay = 2; | ||
835 | } | ||
836 | |||
837 | j = jiffies; | ||
838 | |||
839 | while (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) { | ||
840 | if (delay && ((jiffies - j) >= delay)) { | ||
841 | if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start. | ||
842 | PERROR("Value not available after wait.\n"); | ||
843 | err = ME_ERRNO_INTERNAL; | ||
844 | } else { // External start. | ||
845 | PERROR("Timeout reached.\n"); | ||
846 | err = ME_ERRNO_TIMEOUT; | ||
847 | } | ||
848 | break; | ||
849 | } | ||
850 | // Wait | ||
851 | set_current_state(TASK_INTERRUPTIBLE); | ||
852 | schedule_timeout(1); | ||
853 | |||
854 | if (signal_pending(current)) { | ||
855 | PERROR | ||
856 | ("Wait on external trigger interrupted by signal.\n"); | ||
857 | err = ME_ERRNO_SIGNAL; | ||
858 | break; | ||
859 | } | ||
860 | |||
861 | if (instance->status != ai_status_single_configured) { | ||
862 | PERROR("Wait interrupted by reset.\n"); | ||
863 | err = ME_ERRNO_CANCELLED; | ||
864 | break; | ||
865 | } | ||
866 | } | ||
867 | |||
868 | // Read value. | ||
869 | if (!err) { | ||
870 | val = inl(instance->data_reg) ^ 0x8000; | ||
871 | PDEBUG_REG("data_reg inl(0x%lX+0x%lX)=0x%x\n", | ||
872 | instance->reg_base, | ||
873 | instance->data_reg - instance->reg_base, val); | ||
874 | *value = val & ME4600_AI_MAX_DATA; | ||
875 | } else { | ||
876 | *value = 0xFFFFFFFF; | ||
877 | } | ||
878 | |||
879 | // Restore settings. | ||
880 | spin_lock(instance->ctrl_reg_lock); | ||
881 | tmp = inl(instance->ctrl_reg); | ||
882 | // Clear FIFOs and dissable interrupts. | ||
883 | tmp &= | ||
884 | ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); | ||
885 | tmp |= ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ; | ||
886 | tmp |= | ||
887 | ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | | ||
888 | ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
889 | outl(tmp, instance->ctrl_reg); | ||
890 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
891 | instance->ctrl_reg - instance->reg_base, tmp); | ||
892 | spin_unlock(instance->ctrl_reg_lock); | ||
893 | |||
894 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
895 | |||
896 | ME_SUBDEVICE_EXIT; | ||
897 | |||
898 | return err; | ||
899 | } | ||
900 | |||
901 | static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, | ||
902 | struct file *filep, | ||
903 | meIOStreamConfig_t *config_list, | ||
904 | int count, | ||
905 | meIOStreamTrigger_t *trigger, | ||
906 | int fifo_irq_threshold, int flags) | ||
907 | { | ||
908 | me4600_ai_subdevice_t *instance; | ||
909 | int err = ME_ERRNO_SUCCESS; | ||
910 | int i; // internal multipurpose variable | ||
911 | unsigned long long data_required; | ||
912 | |||
913 | volatile uint32_t entry; | ||
914 | volatile uint32_t ctrl = ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; | ||
915 | volatile uint32_t tmp; // use when current copy of register's value needed | ||
916 | unsigned long cpu_flags; | ||
917 | |||
918 | uint64_t acq_ticks; | ||
919 | uint64_t scan_ticks; | ||
920 | uint64_t conv_ticks; | ||
921 | unsigned int acq_start_ticks_low = trigger->iAcqStartTicksLow; | ||
922 | unsigned int acq_start_ticks_high = trigger->iAcqStartTicksHigh; | ||
923 | unsigned int scan_start_ticks_low = trigger->iScanStartTicksLow; | ||
924 | unsigned int scan_start_ticks_high = trigger->iScanStartTicksHigh; | ||
925 | unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; | ||
926 | unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; | ||
927 | |||
928 | PDEBUG("executed. idx=0\n"); | ||
929 | |||
930 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
931 | |||
932 | if (flags) { | ||
933 | PERROR("Invalid flag specified.\n"); | ||
934 | return ME_ERRNO_INVALID_FLAGS; | ||
935 | } | ||
936 | |||
937 | ME_SUBDEVICE_ENTER | ||
938 | // Convert ticks to 64 bit long values | ||
939 | acq_ticks = | ||
940 | (uint64_t) acq_start_ticks_low + | ||
941 | ((uint64_t) acq_start_ticks_high << 32); | ||
942 | scan_ticks = | ||
943 | (uint64_t) scan_start_ticks_low + | ||
944 | ((uint64_t) scan_start_ticks_high << 32); | ||
945 | conv_ticks = | ||
946 | (uint64_t) conv_start_ticks_low + | ||
947 | ((uint64_t) conv_start_ticks_high << 32); | ||
948 | |||
949 | // Check settings - begin | ||
950 | switch (trigger->iAcqStartTrigType) { | ||
951 | case ME_TRIG_TYPE_SW: | ||
952 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
953 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
954 | break; | ||
955 | |||
956 | default: | ||
957 | PERROR("Invalid acquisition start trigger type specified.\n"); | ||
958 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; | ||
959 | goto ERROR; | ||
960 | break; | ||
961 | } | ||
962 | |||
963 | if ((trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) | ||
964 | && (trigger->iAcqStartTrigEdge != ME_TRIG_EDGE_NONE)) { | ||
965 | PERROR("Invalid acquisition start trigger edge specified.\n"); | ||
966 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
967 | goto ERROR; | ||
968 | } | ||
969 | |||
970 | if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_SW) { | ||
971 | switch (trigger->iAcqStartTrigEdge) { | ||
972 | case ME_TRIG_EDGE_RISING: | ||
973 | case ME_TRIG_EDGE_FALLING: | ||
974 | case ME_TRIG_EDGE_ANY: | ||
975 | break; | ||
976 | |||
977 | default: | ||
978 | PERROR | ||
979 | ("Invalid acquisition start trigger edge specified.\n"); | ||
980 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
981 | goto ERROR; | ||
982 | break; | ||
983 | } | ||
984 | } | ||
985 | |||
986 | if (trigger->iAcqStartTrigChan != ME_TRIG_CHAN_DEFAULT) { | ||
987 | PERROR | ||
988 | ("Invalid acquisition start trigger channel specified.\n"); | ||
989 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; | ||
990 | goto ERROR; | ||
991 | } | ||
992 | |||
993 | if ((acq_ticks < ME4600_AI_MIN_ACQ_TICKS) | ||
994 | || (acq_ticks > ME4600_AI_MAX_ACQ_TICKS)) { | ||
995 | PERROR | ||
996 | ("Invalid acquisition start trigger argument specified.\n"); | ||
997 | err = ME_ERRNO_INVALID_ACQ_START_ARG; | ||
998 | goto ERROR; | ||
999 | } | ||
1000 | |||
1001 | switch (trigger->iScanStartTrigType) { | ||
1002 | |||
1003 | case ME_TRIG_TYPE_TIMER: | ||
1004 | if ((scan_ticks < ME4600_AI_MIN_SCAN_TICKS) | ||
1005 | || (scan_ticks > ME4600_AI_MAX_SCAN_TICKS) | ||
1006 | || (scan_ticks < count * conv_ticks) | ||
1007 | ) { | ||
1008 | PERROR("Invalid scan start argument specified.\n"); | ||
1009 | err = ME_ERRNO_INVALID_SCAN_START_ARG; | ||
1010 | goto ERROR; | ||
1011 | } | ||
1012 | break; | ||
1013 | |||
1014 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
1015 | if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_DIGITAL) { | ||
1016 | PERROR | ||
1017 | ("Invalid scan start trigger type specified (Acq is HW digital)\n"); | ||
1018 | err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; | ||
1019 | goto ERROR; | ||
1020 | } | ||
1021 | break; | ||
1022 | |||
1023 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
1024 | if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_ANALOG) { | ||
1025 | PERROR | ||
1026 | ("Invalid scan start trigger type specified (Acq is HW analog)\n"); | ||
1027 | err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; | ||
1028 | goto ERROR; | ||
1029 | } | ||
1030 | break; | ||
1031 | |||
1032 | case ME_TRIG_TYPE_FOLLOW: | ||
1033 | break; | ||
1034 | |||
1035 | default: | ||
1036 | PERROR("Invalid scan start trigger type specified.\n"); | ||
1037 | err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; | ||
1038 | goto ERROR; | ||
1039 | break; | ||
1040 | } | ||
1041 | |||
1042 | switch (trigger->iConvStartTrigType) { | ||
1043 | |||
1044 | case ME_TRIG_TYPE_TIMER: | ||
1045 | if ((conv_ticks < ME4600_AI_MIN_CHAN_TICKS) | ||
1046 | || (conv_ticks > ME4600_AI_MAX_CHAN_TICKS)) { | ||
1047 | PERROR | ||
1048 | ("Invalid conv start trigger argument specified.\n"); | ||
1049 | err = ME_ERRNO_INVALID_CONV_START_ARG; | ||
1050 | goto ERROR; | ||
1051 | } | ||
1052 | break; | ||
1053 | |||
1054 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
1055 | if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) | ||
1056 | || (trigger->iAcqStartTrigType != | ||
1057 | ME_TRIG_TYPE_EXT_DIGITAL)) { | ||
1058 | PERROR("Invalid conv start trigger type specified.\n"); | ||
1059 | err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; | ||
1060 | goto ERROR; | ||
1061 | } | ||
1062 | break; | ||
1063 | |||
1064 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
1065 | if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) | ||
1066 | || (trigger->iAcqStartTrigType != | ||
1067 | ME_TRIG_TYPE_EXT_ANALOG)) { | ||
1068 | PERROR("Invalid conv start trigger type specified.\n"); | ||
1069 | err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; | ||
1070 | goto ERROR; | ||
1071 | } | ||
1072 | break; | ||
1073 | |||
1074 | default: | ||
1075 | PERROR("Invalid conv start trigger type specified.\n"); | ||
1076 | err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; | ||
1077 | goto ERROR; | ||
1078 | |||
1079 | break; | ||
1080 | } | ||
1081 | /** | ||
1082 | * Aceptable settings: | ||
1083 | * iScanStopTrigType : iAcqStopTrigType | ||
1084 | * | ||
1085 | * ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_NONE -> infinite count with manual stop | ||
1086 | * ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_COUNT -> stop after getting iScanStopCount list of values (iScanStopCount * count) | ||
1087 | * ME_TRIG_TYPE_COUNT : ME_TRIG_TYPE_FOLLOW -> stop after getting iAcqStopCount values (it can stops in midle of the list) | ||
1088 | */ | ||
1089 | switch (trigger->iScanStopTrigType) { | ||
1090 | |||
1091 | case ME_TRIG_TYPE_NONE: | ||
1092 | break; | ||
1093 | |||
1094 | case ME_TRIG_TYPE_COUNT: | ||
1095 | if (trigger->iScanStopCount <= 0) { | ||
1096 | PERROR("Invalid scan stop argument specified.\n"); | ||
1097 | err = ME_ERRNO_INVALID_SCAN_STOP_ARG; | ||
1098 | goto ERROR; | ||
1099 | } | ||
1100 | break; | ||
1101 | |||
1102 | default: | ||
1103 | PERROR("Invalid scan stop trigger type specified.\n"); | ||
1104 | err = ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; | ||
1105 | goto ERROR; | ||
1106 | break; | ||
1107 | } | ||
1108 | |||
1109 | switch (trigger->iAcqStopTrigType) { | ||
1110 | |||
1111 | case ME_TRIG_TYPE_NONE: | ||
1112 | if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { | ||
1113 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1114 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1115 | goto ERROR; | ||
1116 | } | ||
1117 | break; | ||
1118 | |||
1119 | case ME_TRIG_TYPE_FOLLOW: | ||
1120 | if (trigger->iScanStopTrigType != ME_TRIG_TYPE_COUNT) { | ||
1121 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1122 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1123 | goto ERROR; | ||
1124 | } | ||
1125 | break; | ||
1126 | |||
1127 | case ME_TRIG_TYPE_COUNT: | ||
1128 | if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { | ||
1129 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1130 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1131 | goto ERROR; | ||
1132 | } | ||
1133 | |||
1134 | if (trigger->iAcqStopCount <= 0) { | ||
1135 | PERROR | ||
1136 | ("Invalid acquisition or scan stop argument specified.\n"); | ||
1137 | err = ME_ERRNO_INVALID_ACQ_STOP_ARG; | ||
1138 | goto ERROR; | ||
1139 | } | ||
1140 | break; | ||
1141 | |||
1142 | default: | ||
1143 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1144 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1145 | goto ERROR; | ||
1146 | break; | ||
1147 | } | ||
1148 | |||
1149 | if ((count <= 0) || (count > ME4600_AI_LIST_COUNT)) { | ||
1150 | PERROR("Invalid channel list count specified.\n"); | ||
1151 | err = ME_ERRNO_INVALID_CONFIG_LIST_COUNT; | ||
1152 | goto ERROR; | ||
1153 | } | ||
1154 | ///This is general limitation | ||
1155 | // if (fifo_irq_threshold < 0 || fifo_irq_threshold >= ME4600_AI_CIRC_BUF_COUNT) | ||
1156 | ///This is limitation from Windows. I use it for compatibility. | ||
1157 | if (fifo_irq_threshold < 0 | ||
1158 | || fifo_irq_threshold >= ME4600_AI_FIFO_COUNT) { | ||
1159 | PERROR("Invalid fifo irq threshold specified.\n"); | ||
1160 | err = ME_ERRNO_INVALID_FIFO_IRQ_THRESHOLD; | ||
1161 | goto ERROR; | ||
1162 | } | ||
1163 | |||
1164 | if ((config_list[0].iRef == ME_REF_AI_DIFFERENTIAL) | ||
1165 | && (instance->channels == 16)) { | ||
1166 | PERROR | ||
1167 | ("Differential reference is not available on this subdevice.\n"); | ||
1168 | err = ME_ERRNO_INVALID_REF; | ||
1169 | goto ERROR; | ||
1170 | } | ||
1171 | |||
1172 | if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) { | ||
1173 | if (!instance->sh) { | ||
1174 | PERROR | ||
1175 | ("Sample and hold is not available for this board.\n"); | ||
1176 | err = ME_ERRNO_INVALID_FLAGS; | ||
1177 | goto ERROR; | ||
1178 | } | ||
1179 | if (config_list[0].iRef == ME_REF_AI_DIFFERENTIAL) { | ||
1180 | PERROR | ||
1181 | ("Sample and hold is not available in differential mode.\n"); | ||
1182 | err = ME_ERRNO_INVALID_FLAGS; | ||
1183 | goto ERROR; | ||
1184 | } | ||
1185 | } | ||
1186 | |||
1187 | for (i = 0; i < count; i++) { | ||
1188 | if ((config_list[i].iStreamConfig < 0) | ||
1189 | || (config_list[i].iStreamConfig >= instance->ranges_len)) { | ||
1190 | PERROR("Invalid stream config specified.\n"); | ||
1191 | err = ME_ERRNO_INVALID_STREAM_CONFIG; | ||
1192 | goto ERROR; | ||
1193 | } | ||
1194 | |||
1195 | if ((config_list[i].iRef != ME_REF_AI_GROUND) | ||
1196 | && (config_list[i].iRef != ME_REF_AI_DIFFERENTIAL)) { | ||
1197 | PERROR("Invalid references in the list. Ref=0x%x\n", | ||
1198 | config_list[i].iRef); | ||
1199 | err = ME_ERRNO_INVALID_REF; | ||
1200 | goto ERROR; | ||
1201 | } | ||
1202 | |||
1203 | if (config_list[i].iStreamConfig % 2) { // StreamConfig: 1 or 3 | ||
1204 | if (config_list[i].iRef == ME_REF_AI_DIFFERENTIAL) { | ||
1205 | PERROR | ||
1206 | ("Only bipolar modes support differential measurement.\n"); | ||
1207 | err = ME_ERRNO_INVALID_REF; | ||
1208 | goto ERROR; | ||
1209 | } | ||
1210 | } | ||
1211 | |||
1212 | if (config_list[i].iRef != config_list[0].iRef) { | ||
1213 | PERROR | ||
1214 | ("Not all references in the configuration list are equal. Ref[0]=0x%x Ref[%d]=0x%x\n", | ||
1215 | config_list[0].iRef, i, config_list[i].iRef); | ||
1216 | err = ME_ERRNO_INVALID_REF; | ||
1217 | goto ERROR; | ||
1218 | } | ||
1219 | |||
1220 | if ((config_list[i].iRef == ME_REF_AI_DIFFERENTIAL) | ||
1221 | && (config_list[i].iChannel >= 16)) { | ||
1222 | PERROR("Channel not available in differential mode.\n"); | ||
1223 | err = ME_ERRNO_INVALID_CHANNEL; | ||
1224 | goto ERROR; | ||
1225 | } | ||
1226 | |||
1227 | if ((config_list[i].iChannel < 0) | ||
1228 | || (config_list[i].iChannel >= instance->channels)) { | ||
1229 | PERROR("Invalid channel number specified.\n"); | ||
1230 | err = ME_ERRNO_INVALID_CHANNEL; | ||
1231 | goto ERROR; | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | // Check settings - end | ||
1236 | |||
1237 | //Cancel control task | ||
1238 | PDEBUG("Cancel control task.\n"); | ||
1239 | instance->ai_control_task_flag = 0; | ||
1240 | cancel_delayed_work(&instance->ai_control_task); | ||
1241 | |||
1242 | // Work around from Keith Hartley - begin | ||
1243 | if (trigger->iScanStartTrigType == ME_TRIG_TYPE_TIMER) { | ||
1244 | if (count == 1) { | ||
1245 | // The hardware does not work properly with a non-zero scan time | ||
1246 | // if there is only ONE channel in the channel list. In this case | ||
1247 | // we must set the scan time to zero and use the channel time. | ||
1248 | |||
1249 | conv_ticks = scan_ticks; | ||
1250 | trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW; | ||
1251 | } else if (scan_ticks == count * conv_ticks) { | ||
1252 | // Another hardware problem. If the number of scan ticks is | ||
1253 | // exactly equal to the number of channel ticks multiplied by | ||
1254 | // the number of channels then the sampling rate is reduced | ||
1255 | // by half. | ||
1256 | trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW; | ||
1257 | } | ||
1258 | } | ||
1259 | // Work around from Keith Hartley - end | ||
1260 | |||
1261 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1262 | |||
1263 | if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) { | ||
1264 | PERROR("Subdevice is busy.\n"); | ||
1265 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
1266 | ME_SUBDEVICE_EXIT; | ||
1267 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
1268 | } | ||
1269 | |||
1270 | instance->status = ai_status_none; | ||
1271 | spin_lock(instance->ctrl_reg_lock); | ||
1272 | // Stop all actions. Block all interrupts. Clear (disable) FIFOs. | ||
1273 | ctrl = | ||
1274 | ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | | ||
1275 | ME4600_AI_CTRL_BIT_SC_IRQ_RESET; | ||
1276 | |||
1277 | tmp = inl(instance->ctrl_reg); | ||
1278 | // Preserve EXT IRQ and OFFSET settings. Clean other bits. | ||
1279 | tmp &= | ||
1280 | (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET | | ||
1281 | ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET); | ||
1282 | |||
1283 | // Send it to register. | ||
1284 | outl(tmp | ctrl, instance->ctrl_reg); | ||
1285 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1286 | instance->ctrl_reg - instance->reg_base, tmp | ctrl); | ||
1287 | |||
1288 | // Enable channel fifo -> data fifo in stream_start(). | ||
1289 | ctrl |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO; | ||
1290 | outl(tmp | ctrl, instance->ctrl_reg); | ||
1291 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1292 | instance->ctrl_reg - instance->reg_base, tmp | ctrl); | ||
1293 | spin_unlock(instance->ctrl_reg_lock); | ||
1294 | |||
1295 | // Write the channel list | ||
1296 | for (i = 0; i < count; i++) { | ||
1297 | entry = config_list[i].iChannel; | ||
1298 | |||
1299 | switch (config_list[i].iStreamConfig) { | ||
1300 | case 0: //BIPOLAR 10V | ||
1301 | /* | ||
1302 | // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000 | ||
1303 | // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed. | ||
1304 | entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10; | ||
1305 | */ | ||
1306 | break; | ||
1307 | case 1: //UNIPOLAR 10V | ||
1308 | entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_10; | ||
1309 | break; | ||
1310 | case 2: //BIPOLAR 2.5V | ||
1311 | entry |= ME4600_AI_LIST_RANGE_BIPOLAR_2_5; | ||
1312 | break; | ||
1313 | case 3: //UNIPOLAR 2.5V | ||
1314 | entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_2_5; | ||
1315 | break; | ||
1316 | default: | ||
1317 | PERROR_CRITICAL("UNCHECK ERROR in config_list!\n"); | ||
1318 | PERROR_CRITICAL | ||
1319 | ("WRONG range\nPosition:%d Range:0x%04X\n", i, | ||
1320 | config_list[i].iStreamConfig); | ||
1321 | goto VERIFY_ERROR; | ||
1322 | break; | ||
1323 | } | ||
1324 | |||
1325 | switch (config_list[i].iRef) { | ||
1326 | case ME_REF_AI_GROUND: //SINGLE ENDED | ||
1327 | /* | ||
1328 | // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000 | ||
1329 | // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' ==> Do nothing. Removed. | ||
1330 | entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED; | ||
1331 | */ break; | ||
1332 | case ME_REF_AI_DIFFERENTIAL: //DIFFERENTIAL | ||
1333 | entry |= ME4600_AI_LIST_INPUT_DIFFERENTIAL; | ||
1334 | break; | ||
1335 | default: | ||
1336 | PERROR_CRITICAL("UNCHECK ERROR in config_list!\n"); | ||
1337 | PERROR_CRITICAL | ||
1338 | ("WRONG reference\nPosition:%d Reference:0x%04X\n", | ||
1339 | i, config_list[i].iRef); | ||
1340 | goto VERIFY_ERROR; | ||
1341 | break; | ||
1342 | } | ||
1343 | |||
1344 | //Add last entry flag | ||
1345 | if (i == (count - 1)) { | ||
1346 | entry |= ME4600_AI_LIST_LAST_ENTRY; | ||
1347 | } | ||
1348 | |||
1349 | outl(entry, instance->channel_list_reg); | ||
1350 | PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1351 | instance->reg_base, | ||
1352 | instance->channel_list_reg - instance->reg_base, | ||
1353 | entry); | ||
1354 | } | ||
1355 | |||
1356 | // Set triggering registers | ||
1357 | --acq_ticks; | ||
1358 | outl(acq_ticks, instance->chan_pre_timer_reg); | ||
1359 | PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llX\n", | ||
1360 | instance->reg_base, | ||
1361 | instance->chan_pre_timer_reg - instance->reg_base, | ||
1362 | acq_ticks); | ||
1363 | outl(acq_ticks, instance->scan_pre_timer_low_reg); | ||
1364 | PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n", | ||
1365 | instance->reg_base, | ||
1366 | instance->scan_pre_timer_low_reg - instance->reg_base, | ||
1367 | acq_ticks & 0xFFFFFFFF); | ||
1368 | outl((acq_ticks >> 32), instance->scan_pre_timer_high_reg); | ||
1369 | PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n", | ||
1370 | instance->reg_base, | ||
1371 | instance->scan_pre_timer_high_reg - instance->reg_base, | ||
1372 | (acq_ticks >> 32) & 0xFFFFFFFF); | ||
1373 | |||
1374 | // Set triggers | ||
1375 | switch (trigger->iAcqStartTrigType) { | ||
1376 | // Internal | ||
1377 | case ME_TRIG_TYPE_SW: | ||
1378 | // Nothing to set. | ||
1379 | break; | ||
1380 | |||
1381 | // External | ||
1382 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
1383 | ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG; | ||
1384 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
1385 | ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG; | ||
1386 | |||
1387 | // External trigger needs edge's definition | ||
1388 | switch (trigger->iAcqStartTrigEdge) { | ||
1389 | case ME_TRIG_EDGE_RISING: | ||
1390 | // Nothing to set. | ||
1391 | break; | ||
1392 | |||
1393 | case ME_TRIG_EDGE_FALLING: | ||
1394 | ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_FALLING; | ||
1395 | break; | ||
1396 | |||
1397 | case ME_TRIG_EDGE_ANY: | ||
1398 | ctrl |= | ||
1399 | ME4600_AI_CTRL_BIT_EX_TRIG_FALLING | | ||
1400 | ME4600_AI_CTRL_BIT_EX_TRIG_BOTH; | ||
1401 | break; | ||
1402 | |||
1403 | default: | ||
1404 | PERROR_CRITICAL | ||
1405 | ("UNCHECK TRIGGER EDGE in triggers structure!\n"); | ||
1406 | PERROR_CRITICAL | ||
1407 | ("WRONG acquisition start trigger:0x%04X.\n", | ||
1408 | trigger->iAcqStartTrigEdge); | ||
1409 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
1410 | goto VERIFY_ERROR; | ||
1411 | break; | ||
1412 | } | ||
1413 | break; | ||
1414 | |||
1415 | default: | ||
1416 | PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); | ||
1417 | PERROR_CRITICAL("WRONG acquisition start trigger:0x%04X.\n", | ||
1418 | trigger->iAcqStartTrigType); | ||
1419 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; | ||
1420 | goto VERIFY_ERROR; | ||
1421 | break; | ||
1422 | } | ||
1423 | |||
1424 | switch (trigger->iScanStartTrigType) { | ||
1425 | case ME_TRIG_TYPE_TIMER: | ||
1426 | --scan_ticks; | ||
1427 | outl(scan_ticks, instance->scan_timer_low_reg); | ||
1428 | PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n", | ||
1429 | instance->reg_base, | ||
1430 | instance->scan_timer_low_reg - instance->reg_base, | ||
1431 | scan_ticks & 0xFFFFFFFF); | ||
1432 | outl((scan_ticks >> 32), instance->scan_timer_high_reg); | ||
1433 | PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n", | ||
1434 | instance->reg_base, | ||
1435 | instance->scan_timer_high_reg - instance->reg_base, | ||
1436 | (scan_ticks >> 32) & 0xFFFFFFFF); | ||
1437 | |||
1438 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { | ||
1439 | ctrl |= ME4600_AI_CTRL_BIT_MODE_0; | ||
1440 | } else { | ||
1441 | ctrl |= ME4600_AI_CTRL_BIT_MODE_1; | ||
1442 | } | ||
1443 | break; | ||
1444 | |||
1445 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
1446 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
1447 | outl(0, instance->scan_timer_low_reg); | ||
1448 | PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1449 | instance->reg_base, | ||
1450 | instance->scan_timer_low_reg - instance->reg_base, | ||
1451 | 0); | ||
1452 | outl(0, instance->scan_timer_high_reg); | ||
1453 | PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1454 | instance->reg_base, | ||
1455 | instance->scan_timer_high_reg - instance->reg_base, | ||
1456 | 0); | ||
1457 | ctrl |= ME4600_AI_CTRL_BIT_MODE_2; | ||
1458 | break; | ||
1459 | |||
1460 | case ME_TRIG_TYPE_FOLLOW: | ||
1461 | outl(0, instance->scan_timer_low_reg); | ||
1462 | PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1463 | instance->reg_base, | ||
1464 | instance->scan_timer_low_reg - instance->reg_base, | ||
1465 | 0); | ||
1466 | outl(0, instance->scan_timer_high_reg); | ||
1467 | PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1468 | instance->reg_base, | ||
1469 | instance->scan_timer_high_reg - instance->reg_base, | ||
1470 | 0); | ||
1471 | |||
1472 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { | ||
1473 | ctrl |= ME4600_AI_CTRL_BIT_MODE_0; | ||
1474 | } else { | ||
1475 | ctrl |= ME4600_AI_CTRL_BIT_MODE_1; | ||
1476 | } | ||
1477 | break; | ||
1478 | |||
1479 | default: | ||
1480 | PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); | ||
1481 | PERROR_CRITICAL("WRONG scan start trigger:0x%04X.\n", | ||
1482 | trigger->iScanStartTrigType); | ||
1483 | err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; | ||
1484 | goto VERIFY_ERROR; | ||
1485 | break; | ||
1486 | } | ||
1487 | |||
1488 | switch (trigger->iConvStartTrigType) { | ||
1489 | |||
1490 | case ME_TRIG_TYPE_TIMER: | ||
1491 | --conv_ticks; | ||
1492 | outl(conv_ticks, instance->chan_timer_reg); | ||
1493 | PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llX\n", | ||
1494 | instance->reg_base, | ||
1495 | instance->chan_timer_reg - instance->reg_base, | ||
1496 | conv_ticks); | ||
1497 | break; | ||
1498 | |||
1499 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
1500 | case ME_TRIG_TYPE_EXT_ANALOG: | ||
1501 | outl(0, instance->chan_timer_reg); | ||
1502 | PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1503 | instance->reg_base, | ||
1504 | instance->chan_timer_reg - instance->reg_base, 0); | ||
1505 | ctrl |= ME4600_AI_CTRL_BIT_MODE_0 | ME4600_AI_CTRL_BIT_MODE_1; | ||
1506 | break; | ||
1507 | |||
1508 | default: | ||
1509 | PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); | ||
1510 | PERROR_CRITICAL("WRONG conv start trigger:0x%04X.\n", | ||
1511 | trigger->iConvStartTrigType); | ||
1512 | err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; | ||
1513 | goto VERIFY_ERROR; | ||
1514 | |||
1515 | break; | ||
1516 | } | ||
1517 | |||
1518 | //Sample & Hold feature | ||
1519 | if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) { | ||
1520 | if (instance->sh) { | ||
1521 | ctrl |= ME4600_AI_CTRL_BIT_SAMPLE_HOLD; | ||
1522 | } else { | ||
1523 | PERROR_CRITICAL("UNCHECK S&H feature!\n"); | ||
1524 | err = ME_ERRNO_INVALID_FLAGS; | ||
1525 | goto VERIFY_ERROR; | ||
1526 | } | ||
1527 | } | ||
1528 | //Enable IRQs sources but leave latches blocked. | ||
1529 | 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! | ||
1530 | |||
1531 | //Everything is good. Finalize | ||
1532 | spin_lock(instance->ctrl_reg_lock); | ||
1533 | tmp = inl(instance->ctrl_reg); | ||
1534 | |||
1535 | //Preserve EXT IRQ and OFFSET settings. Clean other bits. | ||
1536 | tmp &= | ||
1537 | (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET | | ||
1538 | ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET); | ||
1539 | |||
1540 | // write the control word | ||
1541 | outl(ctrl | tmp, instance->ctrl_reg); | ||
1542 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1543 | instance->ctrl_reg - instance->reg_base, ctrl | tmp); | ||
1544 | spin_unlock(instance->ctrl_reg_lock); | ||
1545 | |||
1546 | //Set the global parameters end exit. | ||
1547 | instance->chan_list_len = count; | ||
1548 | instance->fifo_irq_threshold = fifo_irq_threshold; | ||
1549 | |||
1550 | if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { | ||
1551 | data_required = | ||
1552 | (unsigned long long)trigger->iAcqStopCount * | ||
1553 | (unsigned long long)count; | ||
1554 | if (data_required > UINT_MAX) | ||
1555 | data_required = UINT_MAX; | ||
1556 | instance->data_required = (unsigned int)data_required; | ||
1557 | } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) | ||
1558 | instance->data_required = | ||
1559 | (unsigned long long)trigger->iScanStopCount; | ||
1560 | else | ||
1561 | instance->data_required = 0; | ||
1562 | |||
1563 | // Mark subdevice as configured to work in stream mode. | ||
1564 | instance->status = ai_status_stream_configured; | ||
1565 | |||
1566 | // Deinit single config. Set all entries to NOT_CONFIGURED. | ||
1567 | for (i = 0; i < instance->channels; i++) { | ||
1568 | instance->single_config[i].status = | ||
1569 | ME_SINGLE_CHANNEL_NOT_CONFIGURED; | ||
1570 | } | ||
1571 | |||
1572 | VERIFY_ERROR: // Error in code. Wrong setting check. This should never ever happend! | ||
1573 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
1574 | ERROR: // Error in settings. | ||
1575 | ME_SUBDEVICE_EXIT; | ||
1576 | |||
1577 | return err; | ||
1578 | } | ||
1579 | |||
1580 | static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, | ||
1581 | struct file *filep, | ||
1582 | int time_out, int *count, int flags) | ||
1583 | { | ||
1584 | me4600_ai_subdevice_t *instance; | ||
1585 | int err = ME_ERRNO_SUCCESS; | ||
1586 | unsigned long t; | ||
1587 | unsigned long j; | ||
1588 | int volatile head; | ||
1589 | |||
1590 | PDEBUG("executed. idx=0\n"); | ||
1591 | |||
1592 | if (flags) { | ||
1593 | PERROR("Invalid flag specified.\n"); | ||
1594 | return ME_ERRNO_INVALID_FLAGS; | ||
1595 | } | ||
1596 | |||
1597 | if (time_out < 0) { | ||
1598 | PERROR("Invalid time_out specified.\n"); | ||
1599 | return ME_ERRNO_INVALID_TIMEOUT; | ||
1600 | } | ||
1601 | |||
1602 | if (time_out) { | ||
1603 | t = (time_out * HZ) / 1000; | ||
1604 | |||
1605 | if (t == 0) | ||
1606 | t = 1; | ||
1607 | } else { // Max time. | ||
1608 | t = LONG_MAX; | ||
1609 | } | ||
1610 | |||
1611 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
1612 | |||
1613 | ME_SUBDEVICE_ENTER; | ||
1614 | |||
1615 | j = jiffies; | ||
1616 | |||
1617 | while (1) { | ||
1618 | // Only runing device can generate break. | ||
1619 | head = instance->circ_buf.head; | ||
1620 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1621 | ((head != | ||
1622 | instance->circ_buf.head) | ||
1623 | || | ||
1624 | ((instance->status <= | ||
1625 | ai_status_stream_run_wait) | ||
1626 | && (instance->status >= | ||
1627 | ai_status_stream_end_wait))), | ||
1628 | t); | ||
1629 | |||
1630 | if (head != instance->circ_buf.head) { // New data in buffer. | ||
1631 | break; | ||
1632 | } else if (instance->status == ai_status_stream_end) { // End of work. | ||
1633 | break; | ||
1634 | } else if (instance->status == ai_status_stream_fifo_error) { | ||
1635 | err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
1636 | break; | ||
1637 | } else if (instance->status == ai_status_stream_buffer_error) { | ||
1638 | err = ME_ERRNO_RING_BUFFER_OVERFLOW; | ||
1639 | break; | ||
1640 | } else if (instance->status == ai_status_stream_error) { | ||
1641 | err = ME_ERRNO_INTERNAL; | ||
1642 | break; | ||
1643 | } else if ((jiffies - j) >= t) { | ||
1644 | PERROR("Wait on values timed out.\n"); | ||
1645 | err = ME_ERRNO_TIMEOUT; | ||
1646 | break; | ||
1647 | } else if (signal_pending(current)) { | ||
1648 | PERROR("Wait on values interrupted from signal.\n"); | ||
1649 | err = ME_ERRNO_SIGNAL; | ||
1650 | break; | ||
1651 | } | ||
1652 | // Correct timeout. | ||
1653 | t -= jiffies - j; | ||
1654 | } | ||
1655 | |||
1656 | *count = me_circ_buf_values(&instance->circ_buf); | ||
1657 | |||
1658 | ME_SUBDEVICE_EXIT; | ||
1659 | |||
1660 | return err; | ||
1661 | } | ||
1662 | |||
1663 | static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * | ||
1664 | instance, int *values, | ||
1665 | const int count, | ||
1666 | const int flags) | ||
1667 | { | ||
1668 | int n; | ||
1669 | int i; | ||
1670 | uint32_t value; | ||
1671 | |||
1672 | ///Checking how many datas can be copied. | ||
1673 | n = me_circ_buf_values(&instance->circ_buf); | ||
1674 | if (n <= 0) | ||
1675 | return 0; | ||
1676 | |||
1677 | if (n > count) | ||
1678 | n = count; | ||
1679 | |||
1680 | if (flags & ME_IO_STREAM_READ_FRAMES) { | ||
1681 | if (n < instance->chan_list_len) //Not enough data! | ||
1682 | return 0; | ||
1683 | n -= n % instance->chan_list_len; | ||
1684 | } | ||
1685 | |||
1686 | for (i = 0; i < n; i++) { | ||
1687 | value = *(instance->circ_buf.buf + instance->circ_buf.tail); | ||
1688 | if (put_user(value, values + i)) { | ||
1689 | PERROR("Cannot copy new values to user.\n"); | ||
1690 | return -ME_ERRNO_INTERNAL; | ||
1691 | } | ||
1692 | instance->circ_buf.tail++; | ||
1693 | instance->circ_buf.tail &= instance->circ_buf.mask; | ||
1694 | } | ||
1695 | return n; | ||
1696 | } | ||
1697 | |||
1698 | static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, | ||
1699 | struct file *filep, | ||
1700 | int read_mode, | ||
1701 | int *values, int *count, int flags) | ||
1702 | { | ||
1703 | me4600_ai_subdevice_t *instance; | ||
1704 | int err = ME_ERRNO_SUCCESS; | ||
1705 | int ret; | ||
1706 | |||
1707 | int c = *count; | ||
1708 | int min = c; | ||
1709 | |||
1710 | PDEBUG("executed. idx=0\n"); | ||
1711 | |||
1712 | if (flags & ~ME_IO_STREAM_READ_FRAMES) { | ||
1713 | PERROR("Invalid flag specified.\n"); | ||
1714 | return ME_ERRNO_INVALID_FLAGS; | ||
1715 | } | ||
1716 | |||
1717 | if (!values || !count) { | ||
1718 | PERROR("Request has invalid pointer.\n"); | ||
1719 | return ME_ERRNO_INVALID_POINTER; | ||
1720 | } | ||
1721 | |||
1722 | if (c < 0) { | ||
1723 | PERROR("Request has invalid value's counter.\n"); | ||
1724 | return ME_ERRNO_INVALID_VALUE_COUNT; | ||
1725 | } | ||
1726 | |||
1727 | if ((read_mode != ME_READ_MODE_BLOCKING) | ||
1728 | && (read_mode != ME_READ_MODE_NONBLOCKING)) { | ||
1729 | PERROR("Invalid read mode specified.\n"); | ||
1730 | return ME_ERRNO_INVALID_READ_MODE; | ||
1731 | } | ||
1732 | |||
1733 | if (c == 0) { //You get what you want! Nothing more or less. | ||
1734 | return ME_ERRNO_SUCCESS; | ||
1735 | } | ||
1736 | |||
1737 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
1738 | ME_SUBDEVICE_ENTER; | ||
1739 | |||
1740 | //Check if subdevice is configured. | ||
1741 | if (instance->chan_list_len <= 0) { | ||
1742 | PERROR("Subdevice wasn't configured.\n"); | ||
1743 | ME_SUBDEVICE_EXIT; | ||
1744 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
1745 | } | ||
1746 | |||
1747 | if (flags & ME_IO_STREAM_READ_FRAMES) { | ||
1748 | if (c < instance->chan_list_len) { //Not enough data requested. | ||
1749 | PERROR | ||
1750 | ("When using FRAME_READ mode minimal size is defined by channel list.\n"); | ||
1751 | ME_SUBDEVICE_EXIT; | ||
1752 | return ME_ERRNO_INVALID_VALUE_COUNT; | ||
1753 | } | ||
1754 | } | ||
1755 | |||
1756 | if (c > (ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len)) { // To return acceptable amount of data when user pass too big value. | ||
1757 | min = ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len; | ||
1758 | } | ||
1759 | |||
1760 | if (flags & ME_IO_STREAM_READ_FRAMES) { | ||
1761 | //Wait for whole list. | ||
1762 | if (read_mode == ME_READ_MODE_BLOCKING) { | ||
1763 | min = c - (c % instance->chan_list_len); | ||
1764 | } | ||
1765 | |||
1766 | if (read_mode == ME_READ_MODE_NONBLOCKING) { | ||
1767 | min = instance->chan_list_len; | ||
1768 | } | ||
1769 | } | ||
1770 | |||
1771 | if ((inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { //Working | ||
1772 | //If blocking mode -> wait for data. | ||
1773 | if ((me_circ_buf_values(&instance->circ_buf) < min) | ||
1774 | && (read_mode == ME_READ_MODE_BLOCKING)) { | ||
1775 | wait_event_interruptible(instance->wait_queue, | ||
1776 | ((me_circ_buf_values | ||
1777 | (&instance->circ_buf) >= min) | ||
1778 | || !(inl(instance->status_reg) | ||
1779 | & | ||
1780 | ME4600_AI_STATUS_BIT_FSM))); | ||
1781 | |||
1782 | if (signal_pending(current)) { | ||
1783 | PERROR | ||
1784 | ("Wait on values interrupted from signal.\n"); | ||
1785 | err = ME_ERRNO_SIGNAL; | ||
1786 | } | ||
1787 | } | ||
1788 | } | ||
1789 | |||
1790 | ret = me4600_ai_io_stream_read_get_value(instance, values, c, flags); | ||
1791 | if (ret < 0) { | ||
1792 | err = -ret; | ||
1793 | *count = 0; | ||
1794 | } else if (ret == 0) { | ||
1795 | *count = 0; | ||
1796 | if (instance->status == ai_status_stream_fifo_error) { | ||
1797 | err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
1798 | instance->status = ai_status_stream_end; | ||
1799 | } else if (instance->status == ai_status_stream_buffer_error) { | ||
1800 | err = ME_ERRNO_RING_BUFFER_OVERFLOW; | ||
1801 | instance->status = ai_status_stream_end; | ||
1802 | } else if (instance->status == ai_status_stream_end) { | ||
1803 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
1804 | } else if (instance->status == ai_status_stream_error) { | ||
1805 | err = ME_ERRNO_INTERNAL; | ||
1806 | } else if (instance->status == ai_status_none) { | ||
1807 | PDEBUG("Stream canceled.\n"); | ||
1808 | err = ME_ERRNO_INTERNAL; | ||
1809 | } | ||
1810 | } else { | ||
1811 | *count = ret; | ||
1812 | } | ||
1813 | |||
1814 | ME_SUBDEVICE_EXIT; | ||
1815 | |||
1816 | return err; | ||
1817 | } | ||
1818 | |||
1819 | /** @brief Stop aqusation. Preserve FIFOs. | ||
1820 | * | ||
1821 | * @param instance The subdevice instance (pointer). | ||
1822 | */ | ||
1823 | |||
1824 | static int ai_stop_immediately(me4600_ai_subdevice_t *instance) | ||
1825 | { | ||
1826 | unsigned long cpu_flags = 0; | ||
1827 | volatile uint32_t ctrl; | ||
1828 | const int timeout = HZ / 10; //100ms | ||
1829 | int i; | ||
1830 | |||
1831 | for (i = 0; i <= timeout; i++) { | ||
1832 | spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); | ||
1833 | ctrl = inl(instance->ctrl_reg); | ||
1834 | ctrl &= ~ME4600_AI_CTRL_BIT_STOP; | ||
1835 | ctrl |= | ||
1836 | (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | | ||
1837 | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | | ||
1838 | ME4600_AI_CTRL_BIT_SC_IRQ_RESET); | ||
1839 | outl(ctrl, instance->ctrl_reg); | ||
1840 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1841 | instance->reg_base, | ||
1842 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1843 | spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); | ||
1844 | |||
1845 | if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { // Exit. | ||
1846 | break; | ||
1847 | } | ||
1848 | |||
1849 | PINFO("Wait for stop: %d\n", i + 1); | ||
1850 | //Still working! | ||
1851 | set_current_state(TASK_INTERRUPTIBLE); | ||
1852 | schedule_timeout(1); | ||
1853 | } | ||
1854 | |||
1855 | if (i > timeout) { | ||
1856 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
1857 | return ME_ERRNO_INTERNAL; | ||
1858 | } | ||
1859 | |||
1860 | return ME_ERRNO_SUCCESS; | ||
1861 | } | ||
1862 | |||
1863 | static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, | ||
1864 | struct file *filep, | ||
1865 | int start_mode, int time_out, int flags) | ||
1866 | { | ||
1867 | me4600_ai_subdevice_t *instance; | ||
1868 | int err = ME_ERRNO_SUCCESS; | ||
1869 | unsigned long cpu_flags = 0; | ||
1870 | unsigned long ref; | ||
1871 | unsigned long delay = 0; | ||
1872 | |||
1873 | volatile uint32_t tmp; | ||
1874 | |||
1875 | PDEBUG("executed. idx=0\n"); | ||
1876 | |||
1877 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
1878 | |||
1879 | if (flags) { | ||
1880 | PERROR("Invalid flag specified.\n"); | ||
1881 | return ME_ERRNO_INVALID_FLAGS; | ||
1882 | } | ||
1883 | |||
1884 | if ((start_mode != ME_START_MODE_BLOCKING) | ||
1885 | && (start_mode != ME_START_MODE_NONBLOCKING)) { | ||
1886 | PERROR("Invalid start mode specified.\n"); | ||
1887 | return ME_ERRNO_INVALID_START_MODE; | ||
1888 | } | ||
1889 | |||
1890 | if (time_out < 0) { | ||
1891 | PERROR("Invalid timeout specified.\n"); | ||
1892 | return ME_ERRNO_INVALID_TIMEOUT; | ||
1893 | } | ||
1894 | |||
1895 | if (time_out) { | ||
1896 | delay = (time_out * HZ) / 1000; | ||
1897 | |||
1898 | if (delay == 0) | ||
1899 | delay = 1; | ||
1900 | } | ||
1901 | |||
1902 | ME_SUBDEVICE_ENTER | ||
1903 | spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); | ||
1904 | |||
1905 | tmp = inl(instance->ctrl_reg); | ||
1906 | |||
1907 | if ((tmp & ME4600_AI_STATUS_BIT_FSM)) { | ||
1908 | PERROR("Conversion is already running.\n"); | ||
1909 | spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); | ||
1910 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
1911 | goto ERROR; | ||
1912 | } | ||
1913 | |||
1914 | if (instance->chan_list_len == 0) { //Not configured! | ||
1915 | PERROR("Subdevice is not configured to work in stream mode!\n"); | ||
1916 | spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); | ||
1917 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
1918 | goto ERROR; | ||
1919 | } | ||
1920 | |||
1921 | 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 | ||
1922 | PERROR("Subdevice is configured to work in single mode.\n"); | ||
1923 | spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); | ||
1924 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
1925 | goto ERROR; | ||
1926 | } | ||
1927 | //Reset stop bits. | ||
1928 | tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP; | ||
1929 | outl(tmp, instance->ctrl_reg); | ||
1930 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1931 | instance->ctrl_reg - instance->reg_base, tmp); | ||
1932 | |||
1933 | //Start datas' FIFO. | ||
1934 | tmp |= ME4600_AI_CTRL_BIT_DATA_FIFO; | ||
1935 | //Free stop bits. | ||
1936 | tmp &= ~(ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP); | ||
1937 | outl(tmp, instance->ctrl_reg); | ||
1938 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1939 | instance->ctrl_reg - instance->reg_base, tmp); | ||
1940 | spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); | ||
1941 | |||
1942 | //Cancel control task | ||
1943 | PDEBUG("Cancel control task.\n"); | ||
1944 | instance->ai_control_task_flag = 0; | ||
1945 | cancel_delayed_work(&instance->ai_control_task); | ||
1946 | |||
1947 | //Set the starting values. | ||
1948 | instance->ISM.global_read = 0; | ||
1949 | instance->ISM.read = 0; | ||
1950 | //Clear circular buffer | ||
1951 | instance->circ_buf.head = 0; | ||
1952 | instance->circ_buf.tail = 0; | ||
1953 | |||
1954 | //Set everything. | ||
1955 | ai_data_acquisition_logic(instance); | ||
1956 | |||
1957 | //Set status to 'wait for start' | ||
1958 | instance->status = ai_status_stream_run_wait; | ||
1959 | |||
1960 | // Set control task's timeout | ||
1961 | instance->timeout.delay = delay; | ||
1962 | instance->timeout.start_time = jiffies; | ||
1963 | |||
1964 | //Lets go! Start work | ||
1965 | inl(instance->start_reg); | ||
1966 | PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, | ||
1967 | instance->start_reg - instance->reg_base); | ||
1968 | |||
1969 | // Schedule control task | ||
1970 | instance->ai_control_task_flag = 1; | ||
1971 | queue_delayed_work(instance->me4600_workqueue, | ||
1972 | &instance->ai_control_task, 1); | ||
1973 | |||
1974 | PDEVELOP("Delay:%ld\n", delay); | ||
1975 | |||
1976 | if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start. | ||
1977 | ref = jiffies; | ||
1978 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
1979 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1980 | (instance->status != | ||
1981 | ai_status_stream_run_wait), | ||
1982 | (delay) ? delay + | ||
1983 | 1 : LONG_MAX); | ||
1984 | |||
1985 | if ((instance->status != ai_status_stream_run) | ||
1986 | && (instance->status != ai_status_stream_end)) { | ||
1987 | PDEBUG("Starting stream canceled. %d\n", | ||
1988 | instance->status); | ||
1989 | err = ME_ERRNO_CANCELLED; | ||
1990 | } | ||
1991 | |||
1992 | if (signal_pending(current)) { | ||
1993 | PERROR("Wait on start of state machine interrupted.\n"); | ||
1994 | instance->status = ai_status_none; | ||
1995 | ai_stop_isr(instance); | ||
1996 | err = ME_ERRNO_SIGNAL; | ||
1997 | } else if ((delay) && ((jiffies - ref) > delay)) { | ||
1998 | if (instance->status != ai_status_stream_run) { | ||
1999 | if (instance->status == ai_status_stream_end) { | ||
2000 | PDEBUG("Timeout reached.\n"); | ||
2001 | } else if ((jiffies - ref) > delay + 1) { | ||
2002 | PERROR | ||
2003 | ("Timeout reached. Not handled by control task!\n"); | ||
2004 | ai_stop_isr(instance); | ||
2005 | instance->status = | ||
2006 | ai_status_stream_error; | ||
2007 | } else { | ||
2008 | PERROR | ||
2009 | ("Timeout reached. Signal come but status is strange: %d\n", | ||
2010 | instance->status); | ||
2011 | ai_stop_isr(instance); | ||
2012 | instance->status = | ||
2013 | ai_status_stream_error; | ||
2014 | } | ||
2015 | |||
2016 | instance->ai_control_task_flag = 0; | ||
2017 | cancel_delayed_work(&instance->ai_control_task); | ||
2018 | err = ME_ERRNO_TIMEOUT; | ||
2019 | } | ||
2020 | } | ||
2021 | } | ||
2022 | #ifdef MEDEBUG_INFO | ||
2023 | tmp = inl(instance->ctrl_reg); | ||
2024 | PDEBUG_REG("ctrl_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
2025 | instance->ctrl_reg - instance->reg_base, tmp); | ||
2026 | |||
2027 | PINFO("STATUS_BIT_FSM=%s.\n", | ||
2028 | (tmp & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); | ||
2029 | PINFO("CTRL_BIT_HF_IRQ=%s.\n", | ||
2030 | (tmp & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable"); | ||
2031 | PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", | ||
2032 | (tmp & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : "work"); | ||
2033 | PINFO("CTRL_BIT_SC_IRQ=%s.\n", | ||
2034 | (tmp & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); | ||
2035 | PINFO("CTRL_BIT_SC_RELOAD=%s.\n", | ||
2036 | (tmp & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); | ||
2037 | PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", | ||
2038 | (tmp & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : "work"); | ||
2039 | #endif | ||
2040 | |||
2041 | ERROR: | ||
2042 | ME_SUBDEVICE_EXIT; | ||
2043 | |||
2044 | return err; | ||
2045 | } | ||
2046 | |||
2047 | static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, | ||
2048 | struct file *filep, | ||
2049 | int wait, | ||
2050 | int *status, int *values, int flags) | ||
2051 | { | ||
2052 | me4600_ai_subdevice_t *instance; | ||
2053 | int err = ME_ERRNO_SUCCESS; | ||
2054 | |||
2055 | PDEBUG("executed. idx=0\n"); | ||
2056 | |||
2057 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2058 | |||
2059 | if (flags) { | ||
2060 | PERROR("Invalid flag specified.\n"); | ||
2061 | return ME_ERRNO_INVALID_FLAGS; | ||
2062 | } | ||
2063 | |||
2064 | ME_SUBDEVICE_ENTER; | ||
2065 | |||
2066 | switch (instance->status) { | ||
2067 | case ai_status_single_configured: | ||
2068 | case ai_status_stream_configured: | ||
2069 | case ai_status_stream_end: | ||
2070 | case ai_status_stream_fifo_error: | ||
2071 | case ai_status_stream_buffer_error: | ||
2072 | case ai_status_stream_error: | ||
2073 | *status = ME_STATUS_IDLE; | ||
2074 | break; | ||
2075 | |||
2076 | case ai_status_stream_run_wait: | ||
2077 | case ai_status_stream_run: | ||
2078 | case ai_status_stream_end_wait: | ||
2079 | *status = ME_STATUS_BUSY; | ||
2080 | break; | ||
2081 | |||
2082 | case ai_status_none: | ||
2083 | default: | ||
2084 | *status = | ||
2085 | (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) ? | ||
2086 | ME_STATUS_BUSY : ME_STATUS_IDLE; | ||
2087 | break; | ||
2088 | } | ||
2089 | |||
2090 | if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) { | ||
2091 | // Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
2092 | wait_event_interruptible_timeout(instance->wait_queue, | ||
2093 | ((instance->status != | ||
2094 | ai_status_stream_run_wait) | ||
2095 | && (instance->status != | ||
2096 | ai_status_stream_run) | ||
2097 | && (instance->status != | ||
2098 | ai_status_stream_end_wait)), | ||
2099 | LONG_MAX); | ||
2100 | |||
2101 | if (instance->status != ai_status_stream_end) { | ||
2102 | PDEBUG("Wait for IDLE canceled. %d\n", | ||
2103 | instance->status); | ||
2104 | err = ME_ERRNO_CANCELLED; | ||
2105 | } | ||
2106 | |||
2107 | if (signal_pending(current)) { | ||
2108 | PERROR("Wait for IDLE interrupted.\n"); | ||
2109 | instance->status = ai_status_none; | ||
2110 | ai_stop_isr(instance); | ||
2111 | err = ME_ERRNO_SIGNAL; | ||
2112 | } | ||
2113 | |||
2114 | *status = ME_STATUS_IDLE; | ||
2115 | } | ||
2116 | |||
2117 | *values = me_circ_buf_values(&instance->circ_buf); | ||
2118 | PDEBUG("me_circ_buf_values(&instance->circ_buf)=%d.\n", *values); | ||
2119 | |||
2120 | ME_SUBDEVICE_EXIT; | ||
2121 | |||
2122 | return err; | ||
2123 | } | ||
2124 | |||
2125 | static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, | ||
2126 | struct file *filep, | ||
2127 | int stop_mode, int flags) | ||
2128 | { | ||
2129 | /** | ||
2130 | @note Stop is implemented only in blocking mode. | ||
2131 | @note Function return when state machine is stoped. | ||
2132 | */ | ||
2133 | me4600_ai_subdevice_t *instance; | ||
2134 | unsigned long cpu_flags; | ||
2135 | uint32_t ctrl; | ||
2136 | int ret; | ||
2137 | |||
2138 | PDEBUG("executed. idx=0\n"); | ||
2139 | |||
2140 | if (flags) { | ||
2141 | PERROR("Invalid flag specified.\n"); | ||
2142 | return ME_ERRNO_INVALID_FLAGS; | ||
2143 | } | ||
2144 | |||
2145 | if ((stop_mode != ME_STOP_MODE_IMMEDIATE) | ||
2146 | && (stop_mode != ME_STOP_MODE_LAST_VALUE)) { | ||
2147 | PERROR("Invalid stop mode specified.\n"); | ||
2148 | return ME_ERRNO_INVALID_STOP_MODE; | ||
2149 | } | ||
2150 | |||
2151 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2152 | |||
2153 | ME_SUBDEVICE_ENTER; | ||
2154 | |||
2155 | // Mark as stopping. => Software stop. | ||
2156 | instance->status = ai_status_stream_end_wait; | ||
2157 | |||
2158 | if (stop_mode == ME_STOP_MODE_IMMEDIATE) { | ||
2159 | ret = ai_stop_immediately(instance); | ||
2160 | |||
2161 | if (ret) { | ||
2162 | PERROR("FSM is still busy.\n"); | ||
2163 | ME_SUBDEVICE_EXIT; | ||
2164 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
2165 | } | ||
2166 | instance->ai_control_task_flag = 0; | ||
2167 | |||
2168 | } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { | ||
2169 | // Set stop bit in registry. | ||
2170 | spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); | ||
2171 | ctrl = inl(instance->ctrl_reg); | ||
2172 | ctrl |= ME4600_AI_CTRL_BIT_STOP; | ||
2173 | outl(ctrl, instance->ctrl_reg); | ||
2174 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2175 | instance->reg_base, | ||
2176 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2177 | spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); | ||
2178 | |||
2179 | // Only runing process will interrupt this call. Events are signaled when status change. | ||
2180 | wait_event_interruptible_timeout(instance->wait_queue, | ||
2181 | (instance->status != | ||
2182 | ai_status_stream_end_wait), | ||
2183 | LONG_MAX); | ||
2184 | |||
2185 | if (instance->status != ai_status_stream_end) { | ||
2186 | PDEBUG("Stopping stream canceled.\n"); | ||
2187 | ret = ME_ERRNO_CANCELLED; | ||
2188 | } | ||
2189 | |||
2190 | if (signal_pending(current)) { | ||
2191 | PERROR("Stopping stream interrupted.\n"); | ||
2192 | instance->status = ai_status_none; | ||
2193 | ret = ME_ERRNO_SIGNAL; | ||
2194 | } | ||
2195 | // End of work. | ||
2196 | ai_stop_immediately(instance); | ||
2197 | |||
2198 | } | ||
2199 | |||
2200 | ret = ai_read_data_pooling(instance); | ||
2201 | if (ret > 0) { // Everything fine. More datas put to software buffer. | ||
2202 | instance->status = ai_status_stream_end; | ||
2203 | ret = ME_ERRNO_SUCCESS; | ||
2204 | // Signal that we put last data to software buffer. | ||
2205 | wake_up_interruptible_all(&instance->wait_queue); | ||
2206 | } else if (ret == 0) { // Everything fine. No more datas in FIFO. | ||
2207 | instance->status = ai_status_stream_end; | ||
2208 | ret = ME_ERRNO_SUCCESS; | ||
2209 | } else if (ret == -ME_ERRNO_RING_BUFFER_OVERFLOW) { // Stop is unsuccessful, buffer is overflow. | ||
2210 | instance->status = ai_status_stream_buffer_error; | ||
2211 | ret = ME_ERRNO_SUCCESS; | ||
2212 | } else { // Stop is unsuccessful | ||
2213 | instance->status = ai_status_stream_end; | ||
2214 | ret = -ret; | ||
2215 | } | ||
2216 | |||
2217 | ME_SUBDEVICE_EXIT; | ||
2218 | |||
2219 | return ret; | ||
2220 | } | ||
2221 | |||
2222 | static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, | ||
2223 | int unit, | ||
2224 | int *min, | ||
2225 | int *max, int *maxdata, int *range) | ||
2226 | { | ||
2227 | me4600_ai_subdevice_t *instance; | ||
2228 | int i; | ||
2229 | int r = -1; | ||
2230 | int diff = 21E6; | ||
2231 | |||
2232 | PDEBUG("executed. idx=0\n"); | ||
2233 | |||
2234 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2235 | |||
2236 | if ((*max - *min) < 0) { | ||
2237 | PERROR("Invalid minimum and maximum values specified.\n"); | ||
2238 | return ME_ERRNO_INVALID_MIN_MAX; | ||
2239 | } | ||
2240 | |||
2241 | if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { | ||
2242 | for (i = 0; i < instance->ranges_len; i++) { | ||
2243 | if ((instance->ranges[i].min <= *min) | ||
2244 | && ((instance->ranges[i].max + 1000) >= *max)) { | ||
2245 | if ((instance->ranges[i].max - | ||
2246 | instance->ranges[i].min) - (*max - *min) < | ||
2247 | diff) { | ||
2248 | r = i; | ||
2249 | diff = | ||
2250 | (instance->ranges[i].max - | ||
2251 | instance->ranges[i].min) - (*max - | ||
2252 | *min); | ||
2253 | } | ||
2254 | } | ||
2255 | } | ||
2256 | |||
2257 | if (r < 0) { | ||
2258 | PERROR("No matching range found.\n"); | ||
2259 | return ME_ERRNO_NO_RANGE; | ||
2260 | } else { | ||
2261 | *min = instance->ranges[r].min; | ||
2262 | *max = instance->ranges[r].max; | ||
2263 | *maxdata = ME4600_AI_MAX_DATA; | ||
2264 | *range = r; | ||
2265 | } | ||
2266 | } else { | ||
2267 | PERROR("Invalid physical unit specified.\n"); | ||
2268 | return ME_ERRNO_INVALID_UNIT; | ||
2269 | } | ||
2270 | |||
2271 | return ME_ERRNO_SUCCESS; | ||
2272 | } | ||
2273 | |||
2274 | static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, | ||
2275 | int unit, int *count) | ||
2276 | { | ||
2277 | me4600_ai_subdevice_t *instance; | ||
2278 | |||
2279 | PDEBUG("executed. idx=0\n"); | ||
2280 | |||
2281 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2282 | |||
2283 | if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { | ||
2284 | *count = instance->ranges_len; | ||
2285 | } else { | ||
2286 | *count = 0; | ||
2287 | } | ||
2288 | |||
2289 | return ME_ERRNO_SUCCESS; | ||
2290 | } | ||
2291 | |||
2292 | static int me4600_ai_query_range_info(me_subdevice_t *subdevice, | ||
2293 | int range, | ||
2294 | int *unit, | ||
2295 | int *min, int *max, int *maxdata) | ||
2296 | { | ||
2297 | me4600_ai_subdevice_t *instance; | ||
2298 | |||
2299 | PDEBUG("executed. idx=0\n"); | ||
2300 | |||
2301 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2302 | |||
2303 | if ((range < instance->ranges_len) && (range >= 0)) { | ||
2304 | *unit = ME_UNIT_VOLT; | ||
2305 | *min = instance->ranges[range].min; | ||
2306 | *max = instance->ranges[range].max; | ||
2307 | *maxdata = ME4600_AI_MAX_DATA; | ||
2308 | } else { | ||
2309 | PERROR("Invalid range number specified.\n"); | ||
2310 | return ME_ERRNO_INVALID_RANGE; | ||
2311 | } | ||
2312 | |||
2313 | return ME_ERRNO_SUCCESS; | ||
2314 | } | ||
2315 | |||
2316 | static int me4600_ai_query_timer(me_subdevice_t *subdevice, | ||
2317 | int timer, | ||
2318 | int *base_frequency, | ||
2319 | long long *min_ticks, long long *max_ticks) | ||
2320 | { | ||
2321 | me4600_ai_subdevice_t *instance; | ||
2322 | |||
2323 | PDEBUG("executed. idx=0\n"); | ||
2324 | |||
2325 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2326 | |||
2327 | switch (timer) { | ||
2328 | |||
2329 | case ME_TIMER_ACQ_START: | ||
2330 | *base_frequency = ME4600_AI_BASE_FREQUENCY; | ||
2331 | *min_ticks = ME4600_AI_MIN_ACQ_TICKS; | ||
2332 | *max_ticks = ME4600_AI_MAX_ACQ_TICKS; | ||
2333 | break; | ||
2334 | |||
2335 | case ME_TIMER_SCAN_START: | ||
2336 | *base_frequency = ME4600_AI_BASE_FREQUENCY; | ||
2337 | *min_ticks = ME4600_AI_MIN_SCAN_TICKS; | ||
2338 | *max_ticks = ME4600_AI_MAX_SCAN_TICKS; | ||
2339 | break; | ||
2340 | |||
2341 | case ME_TIMER_CONV_START: | ||
2342 | *base_frequency = ME4600_AI_BASE_FREQUENCY; | ||
2343 | *min_ticks = ME4600_AI_MIN_CHAN_TICKS; | ||
2344 | *max_ticks = ME4600_AI_MAX_CHAN_TICKS; | ||
2345 | break; | ||
2346 | |||
2347 | default: | ||
2348 | PERROR("Invalid timer specified.(0x%04x)\n", timer); | ||
2349 | |||
2350 | return ME_ERRNO_INVALID_TIMER; | ||
2351 | } | ||
2352 | |||
2353 | return ME_ERRNO_SUCCESS; | ||
2354 | } | ||
2355 | |||
2356 | static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, | ||
2357 | int *number) | ||
2358 | { | ||
2359 | me4600_ai_subdevice_t *instance; | ||
2360 | |||
2361 | PDEBUG("executed. idx=0\n"); | ||
2362 | |||
2363 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2364 | *number = instance->channels; | ||
2365 | |||
2366 | return ME_ERRNO_SUCCESS; | ||
2367 | } | ||
2368 | |||
2369 | static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, | ||
2370 | int *type, int *subtype) | ||
2371 | { | ||
2372 | PDEBUG("executed. idx=0\n"); | ||
2373 | |||
2374 | *type = ME_TYPE_AI; | ||
2375 | *subtype = ME_SUBTYPE_STREAMING; | ||
2376 | |||
2377 | return ME_ERRNO_SUCCESS; | ||
2378 | } | ||
2379 | |||
2380 | static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
2381 | { | ||
2382 | PDEBUG("executed. idx=0\n"); | ||
2383 | |||
2384 | *caps = | ||
2385 | ME_CAPS_AI_TRIG_SYNCHRONOUS | ME_CAPS_AI_FIFO | | ||
2386 | ME_CAPS_AI_FIFO_THRESHOLD; | ||
2387 | |||
2388 | return ME_ERRNO_SUCCESS; | ||
2389 | } | ||
2390 | |||
2391 | static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, | ||
2392 | int cap, int *args, int count) | ||
2393 | { | ||
2394 | me4600_ai_subdevice_t *instance; | ||
2395 | int err = ME_ERRNO_SUCCESS; | ||
2396 | |||
2397 | instance = (me4600_ai_subdevice_t *) subdevice; | ||
2398 | |||
2399 | PDEBUG("executed. idx=0\n"); | ||
2400 | |||
2401 | if (count != 1) { | ||
2402 | PERROR("Invalid capability argument count.\n"); | ||
2403 | return ME_ERRNO_INVALID_CAP_ARG_COUNT; | ||
2404 | } | ||
2405 | |||
2406 | switch (cap) { | ||
2407 | case ME_CAP_AI_FIFO_SIZE: | ||
2408 | args[0] = ME4600_AI_FIFO_COUNT; | ||
2409 | break; | ||
2410 | |||
2411 | case ME_CAP_AI_BUFFER_SIZE: | ||
2412 | args[0] = | ||
2413 | (instance->circ_buf.buf) ? ME4600_AI_CIRC_BUF_COUNT : 0; | ||
2414 | break; | ||
2415 | |||
2416 | default: | ||
2417 | PERROR("Invalid capability.\n"); | ||
2418 | err = ME_ERRNO_INVALID_CAP; | ||
2419 | args[0] = 0; | ||
2420 | } | ||
2421 | |||
2422 | return err; | ||
2423 | } | ||
2424 | |||
2425 | void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, | ||
2426 | const uint32_t ctrl_status) | ||
2427 | { | ||
2428 | int to_read; | ||
2429 | |||
2430 | if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work. HF need reseting. | ||
2431 | if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { | ||
2432 | if (ai_read_data(instance, instance->ISM.next) != instance->ISM.next) { //ERROR! | ||
2433 | PERROR | ||
2434 | ("Limited amounts aqusition with TH=0: Circular buffer full!\n"); | ||
2435 | instance->status = | ||
2436 | ai_status_stream_buffer_error; | ||
2437 | } else { | ||
2438 | instance->status = ai_status_stream_end; | ||
2439 | } | ||
2440 | //End of work. | ||
2441 | ai_stop_isr(instance); | ||
2442 | } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { | ||
2443 | instance->ISM.global_read += ME4600_AI_FIFO_HALF; | ||
2444 | |||
2445 | if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! | ||
2446 | PERROR | ||
2447 | ("Limited amounts aqusition with TH = 0: Circular buffer full!\n"); | ||
2448 | //End of work. | ||
2449 | ai_stop_isr(instance); | ||
2450 | instance->status = | ||
2451 | ai_status_stream_buffer_error; | ||
2452 | } else { | ||
2453 | //Continue. | ||
2454 | ai_limited_ISM(instance, irq_status); | ||
2455 | } | ||
2456 | } | ||
2457 | //Signal user. | ||
2458 | wake_up_interruptible_all(&instance->wait_queue); | ||
2459 | } else //if(instance->fifo_irq_threshold) | ||
2460 | { | ||
2461 | if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { | ||
2462 | instance->ISM.read = 0; | ||
2463 | if ((instance->fifo_irq_threshold < ME4600_AI_FIFO_HALF) | ||
2464 | && (!(ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA))) | ||
2465 | { | ||
2466 | to_read = | ||
2467 | ME4600_AI_FIFO_HALF - | ||
2468 | (ME4600_AI_FIFO_HALF % | ||
2469 | instance->fifo_irq_threshold); | ||
2470 | PDEBUG | ||
2471 | ("Limited amounts aqusition with TH != 0: Not fast enough data aqusition! correction=%d\n", | ||
2472 | to_read); | ||
2473 | } else { | ||
2474 | to_read = instance->ISM.next; | ||
2475 | } | ||
2476 | instance->ISM.global_read += to_read; | ||
2477 | |||
2478 | ai_reschedule_SC(instance); | ||
2479 | |||
2480 | if (ai_read_data(instance, to_read) != to_read) { //ERROR! | ||
2481 | PERROR | ||
2482 | ("Limited amounts aqusition with TH != 0: Circular buffer full!\n"); | ||
2483 | //End of work. | ||
2484 | ai_stop_isr(instance); | ||
2485 | instance->status = | ||
2486 | ai_status_stream_buffer_error; | ||
2487 | } else { | ||
2488 | //Continue. | ||
2489 | ai_limited_ISM(instance, irq_status); | ||
2490 | } | ||
2491 | |||
2492 | //Signal user. | ||
2493 | wake_up_interruptible_all(&instance->wait_queue); | ||
2494 | } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { | ||
2495 | instance->ISM.read += ME4600_AI_FIFO_HALF; | ||
2496 | instance->ISM.global_read += ME4600_AI_FIFO_HALF; | ||
2497 | |||
2498 | if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! | ||
2499 | PERROR | ||
2500 | ("Limited amounts aqusition with TH != 0: Circular buffer full!\n"); | ||
2501 | ai_stop_isr(instance); | ||
2502 | |||
2503 | instance->status = | ||
2504 | ai_status_stream_buffer_error; | ||
2505 | //Signal user. | ||
2506 | wake_up_interruptible_all(&instance-> | ||
2507 | wait_queue); | ||
2508 | } else { | ||
2509 | //Countinue. | ||
2510 | ai_limited_ISM(instance, irq_status); | ||
2511 | } | ||
2512 | } | ||
2513 | |||
2514 | if (instance->ISM.global_read >= instance->data_required) { //End of work. Next paranoid pice of code: '>=' instead od '==' only to be sure. | ||
2515 | ai_stop_isr(instance); | ||
2516 | if (instance->status < ai_status_stream_end) { | ||
2517 | instance->status = ai_status_stream_end; | ||
2518 | } | ||
2519 | #ifdef MEDEBUG_ERROR | ||
2520 | if (instance->ISM.global_read > instance->data_required) { //This is security check case. This should never ever happend! | ||
2521 | PERROR | ||
2522 | ("Limited amounts aqusition: Read more data than necessary! data_required=%d < read=%d\n", | ||
2523 | instance->data_required, | ||
2524 | instance->ISM.global_read); | ||
2525 | //Signal error (warning??). | ||
2526 | instance->status = ai_status_stream_error; | ||
2527 | } | ||
2528 | #endif | ||
2529 | } | ||
2530 | } | ||
2531 | } | ||
2532 | |||
2533 | void ai_infinite_isr(me4600_ai_subdevice_t *instance, | ||
2534 | const uint32_t irq_status, const uint32_t ctrl_status) | ||
2535 | { | ||
2536 | int to_read; | ||
2537 | |||
2538 | if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { //next chunck of data -> read fifo | ||
2539 | //Set new state in ISM. | ||
2540 | 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. | ||
2541 | if (instance->fifo_irq_threshold) { | ||
2542 | to_read = | ||
2543 | ME4600_AI_FIFO_HALF - | ||
2544 | (ME4600_AI_FIFO_HALF % | ||
2545 | instance->fifo_irq_threshold); | ||
2546 | if (to_read > instance->fifo_irq_threshold) { | ||
2547 | PDEBUG | ||
2548 | ("Infinite aqusition: Not fast enough data aqusition! TH != 0: correction=%d\n", | ||
2549 | to_read); | ||
2550 | } | ||
2551 | } else { //No threshold specified. | ||
2552 | to_read = ME4600_AI_FIFO_HALF; | ||
2553 | } | ||
2554 | } else { | ||
2555 | to_read = instance->ISM.next; | ||
2556 | } | ||
2557 | |||
2558 | instance->ISM.read += to_read; | ||
2559 | |||
2560 | //Get data | ||
2561 | if (ai_read_data(instance, to_read) != to_read) { //ERROR! | ||
2562 | PERROR("Infinite aqusition: Circular buffer full!\n"); | ||
2563 | ai_stop_isr(instance); | ||
2564 | instance->status = ai_status_stream_buffer_error; | ||
2565 | } else { | ||
2566 | ai_infinite_ISM(instance); | ||
2567 | instance->ISM.global_read += instance->ISM.read; | ||
2568 | instance->ISM.read = 0; | ||
2569 | } | ||
2570 | |||
2571 | //Signal data to user | ||
2572 | wake_up_interruptible_all(&instance->wait_queue); | ||
2573 | } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { //fifo is half full -> read fifo Large blocks only! | ||
2574 | instance->ISM.read += ME4600_AI_FIFO_HALF; | ||
2575 | |||
2576 | if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! | ||
2577 | PERROR("Infinite aqusition: Circular buffer full!\n"); | ||
2578 | ai_stop_isr(instance); | ||
2579 | instance->status = ai_status_stream_buffer_error; | ||
2580 | |||
2581 | //Signal it. | ||
2582 | wake_up_interruptible_all(&instance->wait_queue); | ||
2583 | } else { | ||
2584 | ai_infinite_ISM(instance); | ||
2585 | } | ||
2586 | } | ||
2587 | } | ||
2588 | |||
2589 | static irqreturn_t me4600_ai_isr(int irq, void *dev_id) | ||
2590 | { /// @note This is time critical function! | ||
2591 | uint32_t irq_status; | ||
2592 | uint32_t ctrl_status; | ||
2593 | me4600_ai_subdevice_t *instance = dev_id; | ||
2594 | //int to_read; | ||
2595 | |||
2596 | PDEBUG("executed. idx=0\n"); | ||
2597 | |||
2598 | if (irq != instance->irq) { | ||
2599 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
2600 | return IRQ_NONE; | ||
2601 | } | ||
2602 | |||
2603 | irq_status = inl(instance->irq_status_reg); | ||
2604 | if (! | ||
2605 | (irq_status & | ||
2606 | (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC))) { | ||
2607 | #ifdef MEDEBUG_INFO | ||
2608 | 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. | ||
2609 | PINFO | ||
2610 | ("%ld Shared interrupt. %s(): irq_status_reg=LE_IRQ\n", | ||
2611 | jiffies, __func__); | ||
2612 | } else { | ||
2613 | PINFO | ||
2614 | ("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n", | ||
2615 | jiffies, __func__, irq_status); | ||
2616 | } | ||
2617 | #endif | ||
2618 | return IRQ_NONE; | ||
2619 | } | ||
2620 | |||
2621 | if (!instance->circ_buf.buf) { //Security check. | ||
2622 | PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n"); | ||
2623 | ai_stop_isr(instance); | ||
2624 | return IRQ_HANDLED; | ||
2625 | } | ||
2626 | //Get the status register. | ||
2627 | ctrl_status = inl(instance->status_reg); | ||
2628 | |||
2629 | #ifdef MEDEBUG_INFO | ||
2630 | if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) | ||
2631 | PINFO("HF interrupt active\n"); | ||
2632 | if (irq_status & ME4600_IRQ_STATUS_BIT_SC) | ||
2633 | PINFO("SC interrupt active\n"); | ||
2634 | if (irq_status & ME4600_IRQ_STATUS_BIT_LE) | ||
2635 | PINFO("LE interrupt active\n"); | ||
2636 | #endif | ||
2637 | |||
2638 | //This is safety check! | ||
2639 | if ((irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) | ||
2640 | && (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA)) { | ||
2641 | PDEBUG("HF interrupt active but FIFO under half\n"); | ||
2642 | //Reset HF interrupt latch. | ||
2643 | spin_lock(instance->ctrl_reg_lock); | ||
2644 | outl(ctrl_status | ME4600_AI_CTRL_BIT_HF_IRQ_RESET, | ||
2645 | instance->ctrl_reg); | ||
2646 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2647 | instance->reg_base, | ||
2648 | instance->ctrl_reg - instance->reg_base, | ||
2649 | ctrl_status); | ||
2650 | outl(ctrl_status, instance->ctrl_reg); | ||
2651 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2652 | instance->reg_base, | ||
2653 | instance->ctrl_reg - instance->reg_base, | ||
2654 | ctrl_status); | ||
2655 | spin_unlock(instance->ctrl_reg_lock); | ||
2656 | return IRQ_HANDLED; | ||
2657 | } | ||
2658 | #ifdef MEDEBUG_INFO | ||
2659 | PINFO("STATUS_BIT_FSM=%s.\n", | ||
2660 | (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); | ||
2661 | |||
2662 | PINFO("STATUS_BIT_EF_CHANNEL=%s.\n", | ||
2663 | (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" : | ||
2664 | "empty"); | ||
2665 | PINFO("STATUS_BIT_HF_CHANNEL=%s.\n", | ||
2666 | (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" : | ||
2667 | " > HF"); | ||
2668 | PINFO("STATUS_BIT_FF_CHANNEL=%s.\n", | ||
2669 | (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" : | ||
2670 | "full"); | ||
2671 | |||
2672 | PINFO("STATUS_BIT_EF_DATA=%s.\n", | ||
2673 | (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" : | ||
2674 | "empty"); | ||
2675 | PINFO("STATUS_BIT_HF_DATA=%s.\n", | ||
2676 | (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF"); | ||
2677 | PINFO("STATUS_BIT_FF_DATA=%s.\n", | ||
2678 | (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" : | ||
2679 | "full"); | ||
2680 | |||
2681 | PINFO("CTRL_BIT_HF_IRQ=%s.\n", | ||
2682 | (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable"); | ||
2683 | PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", | ||
2684 | (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : | ||
2685 | "work"); | ||
2686 | PINFO("CTRL_BIT_SC_IRQ=%s.\n", | ||
2687 | (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); | ||
2688 | PINFO("CTRL_BIT_SC_RELOAD=%s.\n", | ||
2689 | (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); | ||
2690 | PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", | ||
2691 | (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : | ||
2692 | "work"); | ||
2693 | #endif | ||
2694 | |||
2695 | //Look for overflow error. | ||
2696 | if (!(ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA)) { | ||
2697 | //FIFO is full. Read datas and reset all settings. | ||
2698 | PERROR("FIFO overflow.\n"); | ||
2699 | ai_read_data(instance, ME4600_AI_FIFO_COUNT); | ||
2700 | ai_stop_isr(instance); | ||
2701 | |||
2702 | instance->status = ai_status_stream_fifo_error; | ||
2703 | //Signal it. | ||
2704 | wake_up_interruptible_all(&instance->wait_queue); | ||
2705 | |||
2706 | return IRQ_HANDLED; | ||
2707 | } | ||
2708 | |||
2709 | if (!instance->data_required) { //This is infinite aqusition. | ||
2710 | #ifdef MEDEBUG_ERROR | ||
2711 | if ((irq_status & | ||
2712 | (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC)) | ||
2713 | == | ||
2714 | (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC)) { | ||
2715 | ///In infinite mode only one interrupt source should be reported! | ||
2716 | PERROR | ||
2717 | ("Error in ISM! Infinite aqusition: HF and SC interrupts active! threshold=%d next=%d ctrl=0x%04X irq_status_reg=0x%04X", | ||
2718 | instance->fifo_irq_threshold, instance->ISM.next, | ||
2719 | ctrl_status, irq_status); | ||
2720 | } | ||
2721 | #endif | ||
2722 | |||
2723 | ai_infinite_isr(instance, irq_status, ctrl_status); | ||
2724 | |||
2725 | #ifdef MEDEBUG_INFO | ||
2726 | ctrl_status = inl(instance->ctrl_reg); | ||
2727 | #endif | ||
2728 | } else { | ||
2729 | |||
2730 | ai_limited_isr(instance, irq_status, ctrl_status); | ||
2731 | ctrl_status = inl(instance->status_reg); | ||
2732 | 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 | ||
2733 | PDEBUG | ||
2734 | ("MISSED HF. data_required=%d ISM.read=%d ISM.global=%d ISM.next=%d\n", | ||
2735 | instance->data_required, instance->ISM.read, | ||
2736 | instance->ISM.global_read, instance->ISM.next); | ||
2737 | ai_limited_isr(instance, ME4600_IRQ_STATUS_BIT_AI_HF, | ||
2738 | ctrl_status); | ||
2739 | } | ||
2740 | } | ||
2741 | |||
2742 | #ifdef MEDEBUG_INFO | ||
2743 | PINFO("STATUS_BIT_FSM=%s.\n", | ||
2744 | (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); | ||
2745 | |||
2746 | PINFO("STATUS_BIT_EF_CHANNEL=%s.\n", | ||
2747 | (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" : | ||
2748 | "empty"); | ||
2749 | PINFO("STATUS_BIT_HF_CHANNEL=%s.\n", | ||
2750 | (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" : | ||
2751 | " > HF"); | ||
2752 | PINFO("STATUS_BIT_FF_CHANNEL=%s.\n", | ||
2753 | (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" : | ||
2754 | "full"); | ||
2755 | |||
2756 | PINFO("STATUS_BIT_EF_DATA=%s.\n", | ||
2757 | (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" : | ||
2758 | "empty"); | ||
2759 | PINFO("STATUS_BIT_HF_DATA=%s.\n", | ||
2760 | (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF"); | ||
2761 | PINFO("STATUS_BIT_FF_DATA=%s.\n", | ||
2762 | (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" : | ||
2763 | "full"); | ||
2764 | |||
2765 | PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", | ||
2766 | (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : | ||
2767 | "work"); | ||
2768 | PINFO("CTRL_BIT_SC_IRQ=%s.\n", | ||
2769 | (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); | ||
2770 | PINFO("CTRL_BIT_SC_RELOAD=%s.\n", | ||
2771 | (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); | ||
2772 | PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", | ||
2773 | (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : | ||
2774 | "work"); | ||
2775 | PINFO("%ld END\n", jiffies); | ||
2776 | #endif | ||
2777 | |||
2778 | return IRQ_HANDLED; | ||
2779 | } | ||
2780 | |||
2781 | /** @brief Stop aqusation of data. Reset interrupts' laches. Clear data's FIFO. | ||
2782 | * | ||
2783 | * @param instance The subdevice instance (pointer). | ||
2784 | */ | ||
2785 | inline void ai_stop_isr(me4600_ai_subdevice_t *instance) | ||
2786 | { /// @note This is soft time critical function! | ||
2787 | register uint32_t tmp; | ||
2788 | |||
2789 | spin_lock(instance->ctrl_reg_lock); | ||
2790 | //Stop all. Reset interrupt laches. Reset data FIFO. | ||
2791 | tmp = inl(instance->ctrl_reg); | ||
2792 | tmp |= | ||
2793 | (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | ||
2794 | | ME4600_AI_CTRL_BIT_LE_IRQ_RESET | | ||
2795 | ME4600_AI_CTRL_BIT_SC_IRQ_RESET); | ||
2796 | tmp &= ~ME4600_AI_CTRL_BIT_DATA_FIFO; | ||
2797 | outl(tmp, instance->ctrl_reg); | ||
2798 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
2799 | instance->ctrl_reg - instance->reg_base, tmp); | ||
2800 | spin_unlock(instance->ctrl_reg_lock); | ||
2801 | } | ||
2802 | |||
2803 | /** @brief Copy data from fifo to circular buffer. | ||
2804 | * | ||
2805 | * @param instance The subdevice instance (pointer). | ||
2806 | * @param count The number of requested data. | ||
2807 | * | ||
2808 | * @return On success: Number of copied values. | ||
2809 | * @return On error: -ME_ERRNO_RING_BUFFER_OVERFLOW. | ||
2810 | */ | ||
2811 | static inline int ai_read_data(me4600_ai_subdevice_t *instance, | ||
2812 | const int count) | ||
2813 | { /// @note This is time critical function! | ||
2814 | int c = count; | ||
2815 | int empty_space; | ||
2816 | int copied = 0; | ||
2817 | int i, j; | ||
2818 | |||
2819 | empty_space = me_circ_buf_space_to_end(&instance->circ_buf); | ||
2820 | if (empty_space <= 0) { | ||
2821 | PDEBUG("Circular buffer full.\n"); | ||
2822 | return -ME_ERRNO_RING_BUFFER_OVERFLOW; | ||
2823 | } | ||
2824 | |||
2825 | if (empty_space < c) { //Copy first part. Max to end of buffer. | ||
2826 | PDEBUG | ||
2827 | ("Try to copy %d values from FIFO to circular buffer (pass 1).\n", | ||
2828 | empty_space); | ||
2829 | for (i = 0; i < empty_space; i++) { | ||
2830 | *(instance->circ_buf.buf + instance->circ_buf.head) = | ||
2831 | (inw(instance->data_reg) ^ 0x8000); | ||
2832 | instance->circ_buf.head++; | ||
2833 | } | ||
2834 | instance->circ_buf.head &= instance->circ_buf.mask; | ||
2835 | c -= empty_space; | ||
2836 | copied = empty_space; | ||
2837 | |||
2838 | empty_space = me_circ_buf_space_to_end(&instance->circ_buf); | ||
2839 | } | ||
2840 | |||
2841 | if (empty_space > 0) { | ||
2842 | j = (empty_space < c) ? empty_space : c; | ||
2843 | PDEBUG | ||
2844 | ("Try to copy %d values from FIFO to circular buffer (pass 2).\n", | ||
2845 | c); | ||
2846 | for (i = 0; i < j; i++) { | ||
2847 | *(instance->circ_buf.buf + instance->circ_buf.head) = | ||
2848 | (inw(instance->data_reg) ^ 0x8000); | ||
2849 | instance->circ_buf.head++; | ||
2850 | } | ||
2851 | instance->circ_buf.head &= instance->circ_buf.mask; | ||
2852 | copied += j; | ||
2853 | } | ||
2854 | return copied; | ||
2855 | } | ||
2856 | |||
2857 | inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance) | ||
2858 | { /// @note This is time critical function! | ||
2859 | register volatile uint32_t ctrl_set, ctrl_reset, tmp; | ||
2860 | |||
2861 | if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { // Only sample counter with reloadnig is working. Reset it. | ||
2862 | PINFO | ||
2863 | ("Only sample counter with reloadnig is working. Reset it.\n"); | ||
2864 | ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET; | ||
2865 | ctrl_reset = ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; | ||
2866 | } 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. | ||
2867 | PINFO | ||
2868 | ("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"); | ||
2869 | ctrl_set = | ||
2870 | ME4600_AI_CTRL_BIT_SC_IRQ_RESET | | ||
2871 | ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2872 | ctrl_reset = | ||
2873 | ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | | ||
2874 | ME4600_AI_CTRL_BIT_HF_IRQ_RESET); | ||
2875 | } 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. | ||
2876 | PINFO | ||
2877 | ("This is HF interrupt for large block.The next interrupt should be from HF, also. Reset HF.\n"); | ||
2878 | ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2879 | ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2880 | } else { //This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF! | ||
2881 | PINFO | ||
2882 | ("This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF!\n"); | ||
2883 | ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2884 | ctrl_reset = 0xFFFFFFFF; | ||
2885 | } | ||
2886 | |||
2887 | //Reset interrupt latch. | ||
2888 | spin_lock(instance->ctrl_reg_lock); | ||
2889 | tmp = inl(instance->ctrl_reg); | ||
2890 | PINFO("ctrl=0x%x ctrl_set=0x%x ctrl_reset=0x%x\n", tmp, ctrl_set, | ||
2891 | ctrl_reset); | ||
2892 | tmp |= ctrl_set; | ||
2893 | outl(tmp, instance->ctrl_reg); | ||
2894 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
2895 | instance->ctrl_reg - instance->reg_base, tmp); | ||
2896 | if (ctrl_reset != 0xFFFFFFFF) { | ||
2897 | outl(tmp & ctrl_reset, instance->ctrl_reg); | ||
2898 | PDEBUG_REG("ctrl_reset outl(0x%lX+0x%lX)=0x%x\n", | ||
2899 | instance->reg_base, | ||
2900 | instance->ctrl_reg - instance->reg_base, | ||
2901 | tmp & ctrl_reset); | ||
2902 | } | ||
2903 | spin_unlock(instance->ctrl_reg_lock); | ||
2904 | |||
2905 | } | ||
2906 | |||
2907 | inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, | ||
2908 | uint32_t irq_status) | ||
2909 | { /// @note This is time critical function! | ||
2910 | register volatile uint32_t ctrl_set, ctrl_reset = 0xFFFFFFFF, tmp; | ||
2911 | |||
2912 | if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work. | ||
2913 | PINFO("No threshold provided. SC ends work.\n"); | ||
2914 | ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2915 | if (instance->data_required > (ME4600_AI_FIFO_COUNT - 1 + instance->ISM.global_read)) { //HF need reseting. | ||
2916 | ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2917 | } | ||
2918 | } else //if(instance->fifo_irq_threshold) | ||
2919 | { | ||
2920 | if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { | ||
2921 | PINFO("Threshold provided. Clear HF latch.\n"); | ||
2922 | ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2923 | |||
2924 | if (instance->fifo_irq_threshold >= (ME4600_AI_FIFO_MAX_SC + instance->ISM.read)) { //This is not the last one. HF need reseting. | ||
2925 | PINFO | ||
2926 | ("The next interrupt is HF. HF need be activating.\n"); | ||
2927 | ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2928 | } | ||
2929 | } | ||
2930 | |||
2931 | if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { | ||
2932 | PINFO("Threshold provided. Restart SC.\n"); | ||
2933 | ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET; | ||
2934 | ctrl_reset &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; | ||
2935 | |||
2936 | if (instance->fifo_irq_threshold >= ME4600_AI_FIFO_MAX_SC) { //This is not the last one. HF need to be activating. | ||
2937 | PINFO | ||
2938 | ("The next interrupt is HF. HF need to be activating.\n"); | ||
2939 | ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
2940 | } | ||
2941 | } | ||
2942 | } | ||
2943 | |||
2944 | //Reset interrupt latch. | ||
2945 | spin_lock(instance->ctrl_reg_lock); | ||
2946 | tmp = inl(instance->ctrl_reg); | ||
2947 | tmp |= ctrl_set; | ||
2948 | outl(tmp, instance->ctrl_reg); | ||
2949 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
2950 | instance->ctrl_reg - instance->reg_base, tmp); | ||
2951 | |||
2952 | if (ctrl_reset != 0xFFFFFFFF) { | ||
2953 | outl(tmp & ctrl_reset, instance->ctrl_reg); | ||
2954 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2955 | instance->reg_base, | ||
2956 | instance->ctrl_reg - instance->reg_base, | ||
2957 | tmp & ctrl_reset); | ||
2958 | } | ||
2959 | spin_unlock(instance->ctrl_reg_lock); | ||
2960 | |||
2961 | } | ||
2962 | |||
2963 | /** @brief Last chunck of datas. We must reschedule sample counter. | ||
2964 | * @note Last chunck. | ||
2965 | * Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. | ||
2966 | * @warning When threshold is wrongly set some IRQ are lost.(!!!) | ||
2967 | */ | ||
2968 | inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance) | ||
2969 | { | ||
2970 | register uint32_t rest; | ||
2971 | |||
2972 | if (instance->data_required <= instance->ISM.global_read) | ||
2973 | return; | ||
2974 | |||
2975 | rest = instance->data_required - instance->ISM.global_read; | ||
2976 | if (rest < instance->fifo_irq_threshold) { //End of work soon .... | ||
2977 | PDEBUG("Rescheduling SC from %d to %d.\n", | ||
2978 | instance->fifo_irq_threshold, rest); | ||
2979 | /// @note Write new value to SC <== DANGER! This is not safe solution! We can miss some inputs. | ||
2980 | outl(rest, instance->sample_counter_reg); | ||
2981 | PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2982 | instance->reg_base, | ||
2983 | instance->sample_counter_reg - instance->reg_base, | ||
2984 | rest); | ||
2985 | instance->fifo_irq_threshold = rest; | ||
2986 | |||
2987 | if (rest < ME4600_AI_FIFO_MAX_SC) { | ||
2988 | instance->ISM.next = rest; | ||
2989 | } else { | ||
2990 | instance->ISM.next = rest % ME4600_AI_FIFO_HALF; | ||
2991 | if (instance->ISM.next + ME4600_AI_FIFO_HALF < | ||
2992 | ME4600_AI_FIFO_MAX_SC) { | ||
2993 | instance->ISM.next += ME4600_AI_FIFO_HALF; | ||
2994 | } | ||
2995 | } | ||
2996 | } | ||
2997 | } | ||
2998 | |||
2999 | /** Start the ISM. All must be reseted before enter to this function. */ | ||
3000 | inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance) | ||
3001 | { | ||
3002 | register uint32_t tmp; | ||
3003 | |||
3004 | if (!instance->data_required) { //This is infinite aqusition. | ||
3005 | if (!instance->fifo_irq_threshold) { //No threshold provided. Set SC to 0.5*FIFO. Clear the SC's latch. | ||
3006 | //Set the sample counter | ||
3007 | outl(ME4600_AI_FIFO_HALF, instance->sample_counter_reg); | ||
3008 | PDEBUG_REG | ||
3009 | ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3010 | instance->reg_base, | ||
3011 | instance->sample_counter_reg - instance->reg_base, | ||
3012 | ME4600_AI_FIFO_HALF); | ||
3013 | } else { //Threshold provided. Set SC to treshold. Clear the SC's latch. | ||
3014 | //Set the sample counter | ||
3015 | outl(instance->fifo_irq_threshold, | ||
3016 | instance->sample_counter_reg); | ||
3017 | PDEBUG_REG | ||
3018 | ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3019 | instance->reg_base, | ||
3020 | instance->sample_counter_reg - instance->reg_base, | ||
3021 | instance->fifo_irq_threshold); | ||
3022 | } | ||
3023 | |||
3024 | if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //Enable only sample counter's interrupt. Set reload bit. Clear the SC's latch. | ||
3025 | spin_lock(instance->ctrl_reg_lock); | ||
3026 | tmp = inl(instance->ctrl_reg); | ||
3027 | tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; | ||
3028 | tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; | ||
3029 | outl(tmp, instance->ctrl_reg); | ||
3030 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3031 | instance->reg_base, | ||
3032 | instance->ctrl_reg - instance->reg_base, | ||
3033 | tmp); | ||
3034 | spin_unlock(instance->ctrl_reg_lock); | ||
3035 | if (!instance->fifo_irq_threshold) { //No threshold provided. Set ISM.next to 0.5*FIFO. | ||
3036 | instance->ISM.next = ME4600_AI_FIFO_HALF; | ||
3037 | } else { //Threshold provided. Set ISM.next to treshold. | ||
3038 | instance->ISM.next = | ||
3039 | instance->fifo_irq_threshold; | ||
3040 | } | ||
3041 | } else { //Enable sample counter's and HF's interrupts. | ||
3042 | spin_lock(instance->ctrl_reg_lock); | ||
3043 | tmp = inl(instance->ctrl_reg); | ||
3044 | tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; | ||
3045 | tmp &= | ||
3046 | ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | | ||
3047 | ME4600_AI_CTRL_BIT_HF_IRQ_RESET); | ||
3048 | outl(tmp, instance->ctrl_reg); | ||
3049 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3050 | instance->reg_base, | ||
3051 | instance->ctrl_reg - instance->reg_base, | ||
3052 | tmp); | ||
3053 | spin_unlock(instance->ctrl_reg_lock); | ||
3054 | |||
3055 | instance->ISM.next = | ||
3056 | instance->fifo_irq_threshold % ME4600_AI_FIFO_HALF; | ||
3057 | if (instance->ISM.next + ME4600_AI_FIFO_HALF < | ||
3058 | ME4600_AI_FIFO_MAX_SC) { | ||
3059 | instance->ISM.next += ME4600_AI_FIFO_HALF; | ||
3060 | } | ||
3061 | } | ||
3062 | } else { //This aqusition is limited to set number of data. | ||
3063 | if (instance->fifo_irq_threshold >= instance->data_required) { //Stupid situation. | ||
3064 | instance->fifo_irq_threshold = 0; | ||
3065 | PDEBUG | ||
3066 | ("Stupid situation: data_required(%d) < threshold(%d).\n", | ||
3067 | instance->fifo_irq_threshold, | ||
3068 | instance->data_required); | ||
3069 | } | ||
3070 | |||
3071 | if (!instance->fifo_irq_threshold) { //No threshold provided. Easy case: HF=read and SC=end. | ||
3072 | //Set the sample counter to data_required. | ||
3073 | outl(instance->data_required, | ||
3074 | instance->sample_counter_reg); | ||
3075 | PDEBUG_REG | ||
3076 | ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3077 | instance->reg_base, | ||
3078 | instance->sample_counter_reg - instance->reg_base, | ||
3079 | instance->data_required); | ||
3080 | |||
3081 | //Reset the latches of sample counter and HF (if SC>FIFO). | ||
3082 | //No SC reload! | ||
3083 | spin_lock(instance->ctrl_reg_lock); | ||
3084 | tmp = inl(instance->ctrl_reg); | ||
3085 | tmp &= | ||
3086 | ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | | ||
3087 | ME4600_AI_CTRL_BIT_SC_RELOAD); | ||
3088 | if (instance->data_required > | ||
3089 | (ME4600_AI_FIFO_COUNT - 1)) { | ||
3090 | tmp &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; | ||
3091 | instance->ISM.next = | ||
3092 | instance->data_required % | ||
3093 | ME4600_AI_FIFO_HALF; | ||
3094 | instance->ISM.next += ME4600_AI_FIFO_HALF; | ||
3095 | |||
3096 | } else { | ||
3097 | instance->ISM.next = instance->data_required; | ||
3098 | } | ||
3099 | outl(tmp, instance->ctrl_reg); | ||
3100 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3101 | instance->reg_base, | ||
3102 | instance->ctrl_reg - instance->reg_base, | ||
3103 | tmp); | ||
3104 | spin_unlock(instance->ctrl_reg_lock); | ||
3105 | |||
3106 | } else { //The most general case. We have concret numbe of required data and threshold. SC=TH | ||
3107 | //Set the sample counter to threshold. | ||
3108 | outl(instance->fifo_irq_threshold, | ||
3109 | instance->sample_counter_reg); | ||
3110 | PDEBUG_REG | ||
3111 | ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3112 | instance->reg_base, | ||
3113 | instance->sample_counter_reg - instance->reg_base, | ||
3114 | instance->fifo_irq_threshold); | ||
3115 | |||
3116 | spin_lock(instance->ctrl_reg_lock); | ||
3117 | tmp = inl(instance->ctrl_reg); | ||
3118 | //In this moment we are sure that SC will come more than once. | ||
3119 | tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; | ||
3120 | |||
3121 | if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //The threshold is so small that we do need HF. | ||
3122 | tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; | ||
3123 | instance->ISM.next = | ||
3124 | instance->fifo_irq_threshold; | ||
3125 | } else { //The threshold is large. The HF must be use. | ||
3126 | tmp &= | ||
3127 | ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | | ||
3128 | ME4600_AI_CTRL_BIT_HF_IRQ_RESET); | ||
3129 | instance->ISM.next = | ||
3130 | instance->fifo_irq_threshold % | ||
3131 | ME4600_AI_FIFO_HALF; | ||
3132 | if (instance->ISM.next + ME4600_AI_FIFO_HALF < | ||
3133 | ME4600_AI_FIFO_MAX_SC) { | ||
3134 | instance->ISM.next += | ||
3135 | ME4600_AI_FIFO_HALF; | ||
3136 | } | ||
3137 | } | ||
3138 | outl(tmp, instance->ctrl_reg); | ||
3139 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3140 | instance->reg_base, | ||
3141 | instance->ctrl_reg - instance->reg_base, | ||
3142 | tmp); | ||
3143 | spin_unlock(instance->ctrl_reg_lock); | ||
3144 | } | ||
3145 | } | ||
3146 | } | ||
3147 | |||
3148 | static int ai_mux_toggler(me4600_ai_subdevice_t *instance) | ||
3149 | { | ||
3150 | uint32_t tmp; | ||
3151 | |||
3152 | PDEBUG("executed. idx=0\n"); | ||
3153 | |||
3154 | outl(0, instance->scan_pre_timer_low_reg); | ||
3155 | PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3156 | instance->reg_base, | ||
3157 | instance->scan_pre_timer_low_reg - instance->reg_base, 0); | ||
3158 | outl(0, instance->scan_pre_timer_high_reg); | ||
3159 | PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3160 | instance->reg_base, | ||
3161 | instance->scan_pre_timer_high_reg - instance->reg_base, 0); | ||
3162 | outl(0, instance->scan_timer_low_reg); | ||
3163 | PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3164 | instance->reg_base, | ||
3165 | instance->scan_timer_low_reg - instance->reg_base, 0); | ||
3166 | outl(0, instance->scan_timer_high_reg); | ||
3167 | PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3168 | instance->reg_base, | ||
3169 | instance->scan_timer_high_reg - instance->reg_base, 0); | ||
3170 | outl(65, instance->chan_timer_reg); | ||
3171 | PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3172 | instance->reg_base, | ||
3173 | instance->chan_timer_reg - instance->reg_base, 65); | ||
3174 | outl(65, instance->chan_pre_timer_reg); | ||
3175 | PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3176 | instance->reg_base, | ||
3177 | instance->chan_pre_timer_reg - instance->reg_base, 65); | ||
3178 | |||
3179 | // Turn on internal reference. | ||
3180 | tmp = inl(instance->ctrl_reg); | ||
3181 | tmp |= ME4600_AI_CTRL_BIT_FULLSCALE; | ||
3182 | outl(tmp, instance->ctrl_reg); | ||
3183 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3184 | instance->ctrl_reg - instance->reg_base, tmp); | ||
3185 | |||
3186 | // Clear data and channel fifo. | ||
3187 | tmp &= | ||
3188 | ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); | ||
3189 | outl(tmp, instance->ctrl_reg); | ||
3190 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3191 | instance->ctrl_reg - instance->reg_base, tmp); | ||
3192 | tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; | ||
3193 | outl(tmp, instance->ctrl_reg); | ||
3194 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3195 | instance->ctrl_reg - instance->reg_base, tmp); | ||
3196 | |||
3197 | // Write channel entry. | ||
3198 | outl(ME4600_AI_LIST_INPUT_DIFFERENTIAL | | ||
3199 | ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31, | ||
3200 | instance->channel_list_reg); | ||
3201 | PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3202 | instance->reg_base, | ||
3203 | instance->channel_list_reg - instance->reg_base, | ||
3204 | ME4600_AI_LIST_INPUT_DIFFERENTIAL | | ||
3205 | ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31); | ||
3206 | |||
3207 | // Start conversion. | ||
3208 | inl(instance->start_reg); | ||
3209 | PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, | ||
3210 | instance->start_reg - instance->reg_base); | ||
3211 | udelay(10); | ||
3212 | |||
3213 | // Clear data and channel fifo. | ||
3214 | tmp &= | ||
3215 | ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); | ||
3216 | outl(tmp, instance->ctrl_reg); | ||
3217 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3218 | instance->ctrl_reg - instance->reg_base, tmp); | ||
3219 | tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; | ||
3220 | outl(tmp, instance->ctrl_reg); | ||
3221 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3222 | instance->ctrl_reg - instance->reg_base, tmp); | ||
3223 | |||
3224 | // Write channel entry. | ||
3225 | // ME4600_AI_LIST_INPUT_SINGLE_ENDED | ME4600_AI_LIST_RANGE_BIPOLAR_10 <= 0x0000 | ||
3226 | outl(ME4600_AI_LIST_INPUT_SINGLE_ENDED | | ||
3227 | ME4600_AI_LIST_RANGE_BIPOLAR_10, instance->channel_list_reg); | ||
3228 | PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3229 | instance->reg_base, | ||
3230 | instance->channel_list_reg - instance->reg_base, | ||
3231 | ME4600_AI_LIST_INPUT_SINGLE_ENDED | | ||
3232 | ME4600_AI_LIST_RANGE_BIPOLAR_10); | ||
3233 | |||
3234 | // Start conversion. | ||
3235 | inl(instance->start_reg); | ||
3236 | PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, | ||
3237 | instance->start_reg - instance->reg_base); | ||
3238 | udelay(10); | ||
3239 | |||
3240 | // Clear control register. | ||
3241 | tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); | ||
3242 | outl(tmp, instance->ctrl_reg); | ||
3243 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3244 | instance->ctrl_reg - instance->reg_base, tmp); | ||
3245 | |||
3246 | return ME_ERRNO_SUCCESS; | ||
3247 | } | ||
3248 | |||
3249 | /** @brief Copy rest of data from fifo to circular buffer. | ||
3250 | * @note Helper for STOP command. After FSM is stopped. | ||
3251 | * @note This is slow function that copy all remainig data from FIFO to buffer. | ||
3252 | * | ||
3253 | * @param instance The subdevice instance (pointer). | ||
3254 | * | ||
3255 | * @return On success: Number of copied values. | ||
3256 | * @return On error: Negative error code -ME_ERRNO_RING_BUFFER_OVERFLOW. | ||
3257 | */ | ||
3258 | static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance) | ||
3259 | { /// @note This is time critical function! | ||
3260 | int empty_space; | ||
3261 | int copied = 0; | ||
3262 | int status = ME_ERRNO_SUCCESS; | ||
3263 | |||
3264 | PDEBUG("Space left in circular buffer = %d.\n", | ||
3265 | me_circ_buf_space(&instance->circ_buf)); | ||
3266 | |||
3267 | while ((empty_space = me_circ_buf_space(&instance->circ_buf))) { | ||
3268 | if (!(status = inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) { //No more data. status = ME_ERRNO_SUCCESS = 0 | ||
3269 | break; | ||
3270 | } | ||
3271 | *(instance->circ_buf.buf + instance->circ_buf.head) = | ||
3272 | (inw(instance->data_reg) ^ 0x8000); | ||
3273 | instance->circ_buf.head++; | ||
3274 | instance->circ_buf.head &= instance->circ_buf.mask; | ||
3275 | } | ||
3276 | |||
3277 | #ifdef MEDEBUG_ERROR | ||
3278 | if (!status) | ||
3279 | PDEBUG | ||
3280 | ("Copied all remaining datas (%d) from FIFO to circular buffer.\n", | ||
3281 | copied); | ||
3282 | else { | ||
3283 | PDEBUG("No more empty space in buffer.\n"); | ||
3284 | PDEBUG("Copied %d datas from FIFO to circular buffer.\n", | ||
3285 | copied); | ||
3286 | PDEBUG("FIFO still not empty.\n"); | ||
3287 | } | ||
3288 | #endif | ||
3289 | return (!status) ? copied : -ME_ERRNO_RING_BUFFER_OVERFLOW; | ||
3290 | } | ||
3291 | |||
3292 | static void me4600_ai_work_control_task(struct work_struct *work) | ||
3293 | { | ||
3294 | me4600_ai_subdevice_t *instance; | ||
3295 | uint32_t status; | ||
3296 | uint32_t ctrl; | ||
3297 | unsigned long cpu_flags = 0; | ||
3298 | int reschedule = 0; | ||
3299 | int signaling = 0; | ||
3300 | |||
3301 | instance = | ||
3302 | container_of((void *)work, me4600_ai_subdevice_t, ai_control_task); | ||
3303 | PINFO("<%s: %ld> executed.\n", __func__, jiffies); | ||
3304 | |||
3305 | status = inl(instance->status_reg); | ||
3306 | PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3307 | instance->status_reg - instance->reg_base, status); | ||
3308 | |||
3309 | switch (instance->status) { // Checking actual mode. | ||
3310 | // Not configured for work. | ||
3311 | case ai_status_none: | ||
3312 | break; | ||
3313 | |||
3314 | //This are stable modes. No need to do anything. (?) | ||
3315 | case ai_status_single_configured: | ||
3316 | case ai_status_stream_configured: | ||
3317 | case ai_status_stream_fifo_error: | ||
3318 | case ai_status_stream_buffer_error: | ||
3319 | case ai_status_stream_error: | ||
3320 | PERROR("Shouldn't be running!.\n"); | ||
3321 | break; | ||
3322 | |||
3323 | // Stream modes | ||
3324 | case ai_status_stream_run_wait: | ||
3325 | if (status & ME4600_AI_STATUS_BIT_FSM) { // ISM started.. | ||
3326 | instance->status = ai_status_stream_run; | ||
3327 | // Signal the end of wait for start. | ||
3328 | signaling = 1; | ||
3329 | // Wait now for stop. | ||
3330 | reschedule = 1; | ||
3331 | break; | ||
3332 | |||
3333 | // Check timeout. | ||
3334 | if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout | ||
3335 | PDEBUG("Timeout reached.\n"); | ||
3336 | // Stop all actions. No conditions! Block interrupts. Reset FIFO => Too late! | ||
3337 | ai_stop_isr(instance); | ||
3338 | |||
3339 | instance->status = ai_status_stream_end; | ||
3340 | |||
3341 | // Signal the end. | ||
3342 | signaling = 1; | ||
3343 | } | ||
3344 | } | ||
3345 | break; | ||
3346 | |||
3347 | case ai_status_stream_run: | ||
3348 | // Wait for stop ISM. | ||
3349 | reschedule = 1; | ||
3350 | break; | ||
3351 | |||
3352 | case ai_status_stream_end_wait: | ||
3353 | if (!(status & ME4600_AI_STATUS_BIT_FSM)) { // ISM stoped. Overwrite ISR. | ||
3354 | instance->status = ai_status_stream_end; | ||
3355 | // Signal the end of wait for stop. | ||
3356 | signaling = 1; | ||
3357 | } else { | ||
3358 | // Wait for stop ISM. | ||
3359 | reschedule = 1; | ||
3360 | } | ||
3361 | break; | ||
3362 | |||
3363 | case ai_status_stream_end: | ||
3364 | //End work. | ||
3365 | if (status & ME4600_AI_STATUS_BIT_FSM) { // Still working? Stop it! | ||
3366 | PERROR | ||
3367 | ("Status is 'ai_status_stream_end' but hardware is still working!\n"); | ||
3368 | spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); | ||
3369 | ctrl = inl(instance->ctrl_reg); | ||
3370 | ctrl |= | ||
3371 | (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | | ||
3372 | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | | ||
3373 | ME4600_AI_CTRL_BIT_SC_IRQ_RESET); | ||
3374 | outl(ctrl, instance->ctrl_reg); | ||
3375 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3376 | instance->reg_base, | ||
3377 | instance->ctrl_reg - instance->reg_base, | ||
3378 | ctrl); | ||
3379 | spin_unlock_irqrestore(instance->ctrl_reg_lock, | ||
3380 | cpu_flags); | ||
3381 | } | ||
3382 | break; | ||
3383 | |||
3384 | default: | ||
3385 | PERROR_CRITICAL("Status is in wrong state (%d)!\n", | ||
3386 | instance->status); | ||
3387 | instance->status = ai_status_stream_error; | ||
3388 | // Signal the end. | ||
3389 | signaling = 1; | ||
3390 | break; | ||
3391 | |||
3392 | } | ||
3393 | |||
3394 | if (signaling) { //Signal it. | ||
3395 | wake_up_interruptible_all(&instance->wait_queue); | ||
3396 | } | ||
3397 | |||
3398 | if (instance->ai_control_task_flag && reschedule) { // Reschedule task | ||
3399 | queue_delayed_work(instance->me4600_workqueue, | ||
3400 | &instance->ai_control_task, 1); | ||
3401 | } else { | ||
3402 | PINFO("<%s> Ending control task.\n", __func__); | ||
3403 | } | ||
3404 | |||
3405 | } | ||
diff --git a/drivers/staging/meilhaus/me4600_ai.h b/drivers/staging/meilhaus/me4600_ai.h deleted file mode 100644 index 7055e44f32ea..000000000000 --- a/drivers/staging/meilhaus/me4600_ai.h +++ /dev/null | |||
@@ -1,175 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ai.h | ||
3 | * | ||
4 | * @brief Meilhaus ME-4000 analog input subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef _ME4600_AI_H_ | ||
29 | #define _ME4600_AI_H_ | ||
30 | |||
31 | #include "mesubdevice.h" | ||
32 | #include "meioctl.h" | ||
33 | #include "mecirc_buf.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | #define ME4600_AI_MAX_DATA 0xFFFF | ||
38 | |||
39 | #ifdef ME_SYNAPSE | ||
40 | # define ME4600_AI_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse | ||
41 | #else | ||
42 | # define ME4600_AI_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB | ||
43 | #endif | ||
44 | #define ME4600_AI_CIRC_BUF_SIZE PAGE_SIZE<<ME4600_AI_CIRC_BUF_SIZE_ORDER // Buffer size in bytes. | ||
45 | |||
46 | #ifdef _CBUFF_32b_t | ||
47 | # define ME4600_AI_CIRC_BUF_COUNT ((ME4600_AI_CIRC_BUF_SIZE) / sizeof(uint32_t)) // Size in values | ||
48 | #else | ||
49 | # define ME4600_AI_CIRC_BUF_COUNT ((ME4600_AI_CIRC_BUF_SIZE) / sizeof(uint16_t)) // Size in values | ||
50 | #endif | ||
51 | |||
52 | #define ME4600_AI_FIFO_HALF 1024 //ME4600_AI_FIFO_COUNT/2 //1024 | ||
53 | #define ME4600_AI_FIFO_MAX_SC 1352 //0.66*ME4600_AI_FIFO_COUNT //1352 | ||
54 | |||
55 | typedef enum ME4600_AI_STATUS { | ||
56 | ai_status_none = 0, | ||
57 | ai_status_single_configured, | ||
58 | ai_status_stream_configured, | ||
59 | ai_status_stream_run_wait, | ||
60 | ai_status_stream_run, | ||
61 | ai_status_stream_end_wait, | ||
62 | ai_status_stream_end, | ||
63 | ai_status_stream_fifo_error, | ||
64 | ai_status_stream_buffer_error, | ||
65 | ai_status_stream_error, | ||
66 | ai_status_last | ||
67 | } ME4600_AI_STATUS; | ||
68 | |||
69 | typedef struct me4600_single_config_entry { | ||
70 | unsigned short status; | ||
71 | uint32_t entry; | ||
72 | uint32_t ctrl; | ||
73 | } me4600_single_config_entry_t; | ||
74 | |||
75 | typedef struct me4600_range_entry { | ||
76 | int min; | ||
77 | int max; | ||
78 | } me4600_range_entry_t; | ||
79 | |||
80 | typedef struct me4600_ai_ISM { | ||
81 | volatile unsigned int global_read; /**< The number of data read in total. */ | ||
82 | volatile unsigned int read; /**< The number of data read for this chunck. */ | ||
83 | volatile unsigned int next; /**< The number of data request by user. */ | ||
84 | } me4600_ai_ISM_t; | ||
85 | |||
86 | typedef struct me4600_ai_timeout { | ||
87 | unsigned long start_time; | ||
88 | unsigned long delay; | ||
89 | } me4600_ai_timeout_t; | ||
90 | |||
91 | /** | ||
92 | * @brief The ME-4000 analog input subdevice class. | ||
93 | */ | ||
94 | typedef struct me4600_ai_subdevice { | ||
95 | /* Inheritance */ | ||
96 | me_subdevice_t base; /**< The subdevice base class. */ | ||
97 | |||
98 | /* Attributes */ | ||
99 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
100 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
101 | |||
102 | /* Hardware feautres */ | ||
103 | unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */ | ||
104 | int isolated; /**< Marks if this subdevice is on an optoisolated device. */ | ||
105 | int sh; /**< Marks if this subdevice has sample and hold devices. */ | ||
106 | |||
107 | unsigned int channels; /**< The number of channels available on this subdevice. */ | ||
108 | me4600_single_config_entry_t single_config[32]; /**< The configuration set for single acquisition. */ | ||
109 | |||
110 | unsigned int data_required; /**< The number of data request by user. */ | ||
111 | unsigned int fifo_irq_threshold; /**< The user adjusted FIFO high water interrupt level. */ | ||
112 | unsigned int chan_list_len; /**< The length of the user defined channel list. */ | ||
113 | |||
114 | me4600_ai_ISM_t ISM; /**< The information request by Interrupt-State-Machine. */ | ||
115 | volatile enum ME4600_AI_STATUS status; /**< The current stream status flag. */ | ||
116 | me4600_ai_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */ | ||
117 | |||
118 | /* Registers *//**< All registers are 32 bits long. */ | ||
119 | unsigned long ctrl_reg; | ||
120 | unsigned long status_reg; | ||
121 | unsigned long channel_list_reg; | ||
122 | unsigned long data_reg; | ||
123 | unsigned long chan_timer_reg; | ||
124 | unsigned long chan_pre_timer_reg; | ||
125 | unsigned long scan_timer_low_reg; | ||
126 | unsigned long scan_timer_high_reg; | ||
127 | unsigned long scan_pre_timer_low_reg; | ||
128 | unsigned long scan_pre_timer_high_reg; | ||
129 | unsigned long start_reg; | ||
130 | unsigned long irq_status_reg; | ||
131 | unsigned long sample_counter_reg; | ||
132 | |||
133 | unsigned int ranges_len; | ||
134 | me4600_range_entry_t ranges[4]; /**< The ranges available on this subdevice. */ | ||
135 | |||
136 | /* Software buffer */ | ||
137 | me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. */ | ||
138 | wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ | ||
139 | |||
140 | struct workqueue_struct *me4600_workqueue; | ||
141 | struct delayed_work ai_control_task; | ||
142 | |||
143 | volatile int ai_control_task_flag; /**< Flag controling reexecuting of control task */ | ||
144 | |||
145 | #ifdef MEDEBUG_DEBUG_REG | ||
146 | unsigned long reg_base; | ||
147 | #endif | ||
148 | } me4600_ai_subdevice_t; | ||
149 | |||
150 | /** | ||
151 | * @brief The constructor to generate a ME-4000 analog input subdevice instance. | ||
152 | * | ||
153 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
154 | * @param channels The number of analog input channels available on this subdevice. | ||
155 | * @param channels The number of analog input ranges available on this subdevice. | ||
156 | * @param isolated Flag indicating if this device is opto isolated. | ||
157 | * @param sh Flag indicating if sample and hold devices are available. | ||
158 | * @param irq The irq number assigned by PCI BIOS. | ||
159 | * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. | ||
160 | * | ||
161 | * @return Pointer to new instance on success.\n | ||
162 | * NULL on error. | ||
163 | */ | ||
164 | me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base, | ||
165 | unsigned int channels, | ||
166 | unsigned int ranges, | ||
167 | int isolated, | ||
168 | int sh, | ||
169 | int irq, | ||
170 | spinlock_t * ctrl_reg_lock, | ||
171 | struct workqueue_struct | ||
172 | *me4600_wq); | ||
173 | |||
174 | #endif | ||
175 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_ai_reg.h b/drivers/staging/meilhaus/me4600_ai_reg.h deleted file mode 100644 index 083fac7685f5..000000000000 --- a/drivers/staging/meilhaus/me4600_ai_reg.h +++ /dev/null | |||
@@ -1,107 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ai_reg.h | ||
3 | * | ||
4 | * @brief ME-4000 analog input subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_AI_REG_H_ | ||
28 | #define _ME4600_AI_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME4600_AI_CTRL_REG 0x74 // _/W | ||
33 | #define ME4600_AI_STATUS_REG 0x74 // R/_ | ||
34 | #define ME4600_AI_CHANNEL_LIST_REG 0x78 // _/W | ||
35 | #define ME4600_AI_DATA_REG 0x7C // R/_ | ||
36 | #define ME4600_AI_CHAN_TIMER_REG 0x80 // _/W | ||
37 | #define ME4600_AI_CHAN_PRE_TIMER_REG 0x84 // _/W | ||
38 | #define ME4600_AI_SCAN_TIMER_LOW_REG 0x88 // _/W | ||
39 | #define ME4600_AI_SCAN_TIMER_HIGH_REG 0x8C // _/W | ||
40 | #define ME4600_AI_SCAN_PRE_TIMER_LOW_REG 0x90 // _/W | ||
41 | #define ME4600_AI_SCAN_PRE_TIMER_HIGH_REG 0x94 // _/W | ||
42 | #define ME4600_AI_START_REG 0x98 // R/_ | ||
43 | |||
44 | #define ME4600_AI_SAMPLE_COUNTER_REG 0xC0 // _/W | ||
45 | |||
46 | #define ME4600_AI_CTRL_BIT_MODE_0 0x00000001 | ||
47 | #define ME4600_AI_CTRL_BIT_MODE_1 0x00000002 | ||
48 | #define ME4600_AI_CTRL_BIT_MODE_2 0x00000004 | ||
49 | #define ME4600_AI_CTRL_BIT_SAMPLE_HOLD 0x00000008 | ||
50 | #define ME4600_AI_CTRL_BIT_IMMEDIATE_STOP 0x00000010 | ||
51 | #define ME4600_AI_CTRL_BIT_STOP 0x00000020 | ||
52 | #define ME4600_AI_CTRL_BIT_CHANNEL_FIFO 0x00000040 | ||
53 | #define ME4600_AI_CTRL_BIT_DATA_FIFO 0x00000080 | ||
54 | #define ME4600_AI_CTRL_BIT_FULLSCALE 0x00000100 | ||
55 | #define ME4600_AI_CTRL_BIT_OFFSET 0x00000200 | ||
56 | #define ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG 0x00000400 | ||
57 | #define ME4600_AI_CTRL_BIT_EX_TRIG 0x00000800 | ||
58 | #define ME4600_AI_CTRL_BIT_EX_TRIG_FALLING 0x00001000 | ||
59 | #define ME4600_AI_CTRL_BIT_EX_IRQ 0x00002000 | ||
60 | #define ME4600_AI_CTRL_BIT_EX_IRQ_RESET 0x00004000 | ||
61 | #define ME4600_AI_CTRL_BIT_LE_IRQ 0x00008000 | ||
62 | #define ME4600_AI_CTRL_BIT_LE_IRQ_RESET 0x00010000 | ||
63 | #define ME4600_AI_CTRL_BIT_HF_IRQ 0x00020000 | ||
64 | #define ME4600_AI_CTRL_BIT_HF_IRQ_RESET 0x00040000 | ||
65 | #define ME4600_AI_CTRL_BIT_SC_IRQ 0x00080000 | ||
66 | #define ME4600_AI_CTRL_BIT_SC_IRQ_RESET 0x00100000 | ||
67 | #define ME4600_AI_CTRL_BIT_SC_RELOAD 0x00200000 | ||
68 | #define ME4600_AI_CTRL_BIT_EX_TRIG_BOTH 0x80000000 | ||
69 | |||
70 | #define ME4600_AI_STATUS_BIT_EF_CHANNEL 0x00400000 | ||
71 | #define ME4600_AI_STATUS_BIT_HF_CHANNEL 0x00800000 | ||
72 | #define ME4600_AI_STATUS_BIT_FF_CHANNEL 0x01000000 | ||
73 | #define ME4600_AI_STATUS_BIT_EF_DATA 0x02000000 | ||
74 | #define ME4600_AI_STATUS_BIT_HF_DATA 0x04000000 | ||
75 | #define ME4600_AI_STATUS_BIT_FF_DATA 0x08000000 | ||
76 | #define ME4600_AI_STATUS_BIT_LE 0x10000000 | ||
77 | #define ME4600_AI_STATUS_BIT_FSM 0x20000000 | ||
78 | |||
79 | #define ME4600_AI_CTRL_RPCI_FIFO 0x40000000 //Always set to zero! | ||
80 | |||
81 | #define ME4600_AI_BASE_FREQUENCY 33E6 | ||
82 | |||
83 | #define ME4600_AI_MIN_ACQ_TICKS 66LL | ||
84 | #define ME4600_AI_MAX_ACQ_TICKS 0xFFFFFFFFLL | ||
85 | |||
86 | #define ME4600_AI_MIN_SCAN_TICKS 66LL | ||
87 | #define ME4600_AI_MAX_SCAN_TICKS 0xFFFFFFFFFLL | ||
88 | |||
89 | #define ME4600_AI_MIN_CHAN_TICKS 66LL | ||
90 | #define ME4600_AI_MAX_CHAN_TICKS 0xFFFFFFFFLL | ||
91 | |||
92 | #define ME4600_AI_FIFO_COUNT 2048 | ||
93 | |||
94 | #define ME4600_AI_LIST_COUNT 1024 | ||
95 | |||
96 | #define ME4600_AI_LIST_INPUT_SINGLE_ENDED 0x000 | ||
97 | #define ME4600_AI_LIST_INPUT_DIFFERENTIAL 0x020 | ||
98 | |||
99 | #define ME4600_AI_LIST_RANGE_BIPOLAR_10 0x000 | ||
100 | #define ME4600_AI_LIST_RANGE_BIPOLAR_2_5 0x040 | ||
101 | #define ME4600_AI_LIST_RANGE_UNIPOLAR_10 0x080 | ||
102 | #define ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 0x0C0 | ||
103 | |||
104 | #define ME4600_AI_LIST_LAST_ENTRY 0x100 | ||
105 | |||
106 | #endif | ||
107 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_ao.c b/drivers/staging/meilhaus/me4600_ao.c deleted file mode 100644 index 4000dac057ed..000000000000 --- a/drivers/staging/meilhaus/me4600_ao.c +++ /dev/null | |||
@@ -1,5974 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ao.c | ||
3 | * | ||
4 | * @brief ME-4000 analog output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | ///Common part. (For normal and Bosch builds.) | ||
33 | |||
34 | /* Includes | ||
35 | */ | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | |||
39 | #include <linux/slab.h> | ||
40 | #include <linux/spinlock.h> | ||
41 | #include <linux/io.h> | ||
42 | #include <linux/uaccess.h> | ||
43 | #include <linux/types.h> | ||
44 | #include <linux/version.h> | ||
45 | #include <linux/interrupt.h> | ||
46 | #include <linux/delay.h> | ||
47 | |||
48 | #include "medefines.h" | ||
49 | #include "meinternal.h" | ||
50 | #include "meerror.h" | ||
51 | |||
52 | #include "medebug.h" | ||
53 | #include "meids.h" | ||
54 | #include "me4600_reg.h" | ||
55 | #include "me4600_ao_reg.h" | ||
56 | #include "me4600_ao.h" | ||
57 | |||
58 | /* Defines | ||
59 | */ | ||
60 | |||
61 | static int me4600_ao_query_range_by_min_max(me_subdevice_t *subdevice, | ||
62 | int unit, | ||
63 | int *min, | ||
64 | int *max, int *maxdata, int *range); | ||
65 | |||
66 | static int me4600_ao_query_number_ranges(me_subdevice_t *subdevice, | ||
67 | int unit, int *count); | ||
68 | |||
69 | static int me4600_ao_query_range_info(me_subdevice_t *subdevice, | ||
70 | int range, | ||
71 | int *unit, | ||
72 | int *min, int *max, int *maxdata); | ||
73 | |||
74 | static int me4600_ao_query_timer(me_subdevice_t *subdevice, | ||
75 | int timer, | ||
76 | int *base_frequency, | ||
77 | long long *min_ticks, long long *max_ticks); | ||
78 | |||
79 | static int me4600_ao_query_number_channels(me_subdevice_t *subdevice, | ||
80 | int *number); | ||
81 | |||
82 | static int me4600_ao_query_subdevice_type(me_subdevice_t *subdevice, | ||
83 | int *type, int *subtype); | ||
84 | |||
85 | static int me4600_ao_query_subdevice_caps(me_subdevice_t *subdevice, | ||
86 | int *caps); | ||
87 | |||
88 | static int me4600_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, | ||
89 | int cap, int *args, int count); | ||
90 | |||
91 | #ifndef BOSCH | ||
92 | /// @note NORMAL BUILD | ||
93 | /// @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
94 | /* Includes | ||
95 | */ | ||
96 | |||
97 | # include <linux/workqueue.h> | ||
98 | |||
99 | /* Defines | ||
100 | */ | ||
101 | |||
102 | /** Remove subdevice. | ||
103 | */ | ||
104 | static void me4600_ao_destructor(struct me_subdevice *subdevice); | ||
105 | |||
106 | /** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'. | ||
107 | */ | ||
108 | static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, | ||
109 | struct file *filep, int flags); | ||
110 | |||
111 | /** Set output as single | ||
112 | */ | ||
113 | static int me4600_ao_io_single_config(me_subdevice_t *subdevice, | ||
114 | struct file *filep, | ||
115 | int channel, | ||
116 | int single_config, | ||
117 | int ref, | ||
118 | int trig_chan, | ||
119 | int trig_type, int trig_edge, int flags); | ||
120 | |||
121 | /** Pass to user actual value of output. | ||
122 | */ | ||
123 | static int me4600_ao_io_single_read(me_subdevice_t *subdevice, | ||
124 | struct file *filep, | ||
125 | int channel, | ||
126 | int *value, int time_out, int flags); | ||
127 | |||
128 | /** Write to output requed value. | ||
129 | */ | ||
130 | static int me4600_ao_io_single_write(me_subdevice_t *subdevice, | ||
131 | struct file *filep, | ||
132 | int channel, | ||
133 | int value, int time_out, int flags); | ||
134 | |||
135 | /** Set output as streamed device. | ||
136 | */ | ||
137 | static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, | ||
138 | struct file *filep, | ||
139 | meIOStreamConfig_t *config_list, | ||
140 | int count, | ||
141 | meIOStreamTrigger_t *trigger, | ||
142 | int fifo_irq_threshold, int flags); | ||
143 | |||
144 | /** Wait for / Check empty space in buffer. | ||
145 | */ | ||
146 | static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, | ||
147 | struct file *filep, | ||
148 | int time_out, int *count, int flags); | ||
149 | |||
150 | /** Start streaming. | ||
151 | */ | ||
152 | static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, | ||
153 | struct file *filep, | ||
154 | int start_mode, int time_out, int flags); | ||
155 | |||
156 | /** Check actual state. / Wait for end. | ||
157 | */ | ||
158 | static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, | ||
159 | struct file *filep, | ||
160 | int wait, | ||
161 | int *status, int *values, int flags); | ||
162 | |||
163 | /** Stop streaming. | ||
164 | */ | ||
165 | static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, | ||
166 | struct file *filep, | ||
167 | int stop_mode, int flags); | ||
168 | |||
169 | /** Write datas to buffor. | ||
170 | */ | ||
171 | static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, | ||
172 | struct file *filep, | ||
173 | int write_mode, | ||
174 | int *values, int *count, int flags); | ||
175 | |||
176 | /** Interrupt handler. Copy from buffer to FIFO. | ||
177 | */ | ||
178 | static irqreturn_t me4600_ao_isr(int irq, void *dev_id); | ||
179 | /** Copy data from circular buffer to fifo (fast) in wraparound mode. | ||
180 | */ | ||
181 | inline int ao_write_data_wraparound(me4600_ao_subdevice_t *instance, int count, | ||
182 | int start_pos); | ||
183 | |||
184 | /** Copy data from circular buffer to fifo (fast). | ||
185 | */ | ||
186 | inline int ao_write_data(me4600_ao_subdevice_t *instance, int count, | ||
187 | int start_pos); | ||
188 | |||
189 | /** Copy data from circular buffer to fifo (slow). | ||
190 | */ | ||
191 | inline int ao_write_data_pooling(me4600_ao_subdevice_t *instance, int count, | ||
192 | int start_pos); | ||
193 | |||
194 | /** Copy data from user space to circular buffer. | ||
195 | */ | ||
196 | inline int ao_get_data_from_user(me4600_ao_subdevice_t *instance, int count, | ||
197 | int *user_values); | ||
198 | |||
199 | /** Stop presentation. Preserve FIFOs. | ||
200 | */ | ||
201 | inline int ao_stop_immediately(me4600_ao_subdevice_t *instance); | ||
202 | |||
203 | /** Task for asynchronical state verifying. | ||
204 | */ | ||
205 | static void me4600_ao_work_control_task(struct work_struct *work); | ||
206 | /* Functions | ||
207 | */ | ||
208 | |||
209 | static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, | ||
210 | struct file *filep, int flags) | ||
211 | { | ||
212 | me4600_ao_subdevice_t *instance; | ||
213 | int err = ME_ERRNO_SUCCESS; | ||
214 | uint32_t tmp; | ||
215 | |||
216 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
217 | |||
218 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
219 | |||
220 | if (flags) { | ||
221 | PERROR("Invalid flag specified.\n"); | ||
222 | return ME_ERRNO_INVALID_FLAGS; | ||
223 | } | ||
224 | |||
225 | ME_SUBDEVICE_ENTER; | ||
226 | |||
227 | instance->status = ao_status_none; | ||
228 | instance->ao_control_task_flag = 0; | ||
229 | cancel_delayed_work(&instance->ao_control_task); | ||
230 | instance->timeout.delay = 0; | ||
231 | instance->timeout.start_time = jiffies; | ||
232 | |||
233 | //Stop state machine. | ||
234 | err = ao_stop_immediately(instance); | ||
235 | |||
236 | //Remove from synchronous start. | ||
237 | spin_lock(instance->preload_reg_lock); | ||
238 | tmp = inl(instance->preload_reg); | ||
239 | tmp &= | ||
240 | ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance-> | ||
241 | ao_idx); | ||
242 | outl(tmp, instance->preload_reg); | ||
243 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
244 | instance->preload_reg - instance->reg_base, tmp); | ||
245 | *instance->preload_flags &= | ||
246 | ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance-> | ||
247 | ao_idx); | ||
248 | spin_unlock(instance->preload_reg_lock); | ||
249 | |||
250 | //Set single mode, dissable FIFO, dissable external trigger, set output to analog, block interrupt. | ||
251 | outl(ME4600_AO_MODE_SINGLE | ME4600_AO_CTRL_BIT_STOP | | ||
252 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_RESET_IRQ, | ||
253 | instance->ctrl_reg); | ||
254 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
255 | instance->ctrl_reg - instance->reg_base, | ||
256 | ME4600_AO_MODE_SINGLE | ME4600_AO_CTRL_BIT_STOP | | ||
257 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | | ||
258 | ME4600_AO_CTRL_BIT_RESET_IRQ); | ||
259 | |||
260 | //Set output to 0V | ||
261 | outl(0x8000, instance->single_reg); | ||
262 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
263 | instance->single_reg - instance->reg_base, 0x8000); | ||
264 | |||
265 | instance->circ_buf.head = 0; | ||
266 | instance->circ_buf.tail = 0; | ||
267 | instance->preloaded_count = 0; | ||
268 | instance->data_count = 0; | ||
269 | instance->single_value = 0x8000; | ||
270 | instance->single_value_in_fifo = 0x8000; | ||
271 | |||
272 | //Set status to signal that device is unconfigured. | ||
273 | instance->status = ao_status_none; | ||
274 | |||
275 | //Signal reset if user is on wait. | ||
276 | wake_up_interruptible_all(&instance->wait_queue); | ||
277 | |||
278 | ME_SUBDEVICE_EXIT; | ||
279 | |||
280 | return err; | ||
281 | } | ||
282 | |||
283 | static int me4600_ao_io_single_config(me_subdevice_t *subdevice, | ||
284 | struct file *filep, | ||
285 | int channel, | ||
286 | int single_config, | ||
287 | int ref, | ||
288 | int trig_chan, | ||
289 | int trig_type, int trig_edge, int flags) | ||
290 | { | ||
291 | me4600_ao_subdevice_t *instance; | ||
292 | int err = ME_ERRNO_SUCCESS; | ||
293 | uint32_t ctrl; | ||
294 | uint32_t sync; | ||
295 | unsigned long cpu_flags; | ||
296 | |||
297 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
298 | |||
299 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
300 | |||
301 | // Checking parameters | ||
302 | if (flags) { | ||
303 | PERROR | ||
304 | ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n"); | ||
305 | return ME_ERRNO_INVALID_FLAGS; | ||
306 | } | ||
307 | |||
308 | switch (trig_type) { | ||
309 | case ME_TRIG_TYPE_SW: | ||
310 | if (trig_edge != ME_TRIG_EDGE_NONE) { | ||
311 | PERROR | ||
312 | ("Invalid trigger edge. Software trigger has not edge.\n"); | ||
313 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
314 | } | ||
315 | break; | ||
316 | |||
317 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
318 | switch (trig_edge) { | ||
319 | case ME_TRIG_EDGE_ANY: | ||
320 | case ME_TRIG_EDGE_RISING: | ||
321 | case ME_TRIG_EDGE_FALLING: | ||
322 | break; | ||
323 | |||
324 | default: | ||
325 | PERROR("Invalid trigger edge.\n"); | ||
326 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
327 | } | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | PERROR | ||
332 | ("Invalid trigger type. Trigger must be software or digital.\n"); | ||
333 | return ME_ERRNO_INVALID_TRIG_TYPE; | ||
334 | } | ||
335 | |||
336 | if ((trig_chan != ME_TRIG_CHAN_DEFAULT) | ||
337 | && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) { | ||
338 | PERROR("Invalid trigger channel specified.\n"); | ||
339 | return ME_ERRNO_INVALID_TRIG_CHAN; | ||
340 | } | ||
341 | |||
342 | if (ref != ME_REF_AO_GROUND) { | ||
343 | PERROR | ||
344 | ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n"); | ||
345 | return ME_ERRNO_INVALID_REF; | ||
346 | } | ||
347 | |||
348 | if (single_config != 0) { | ||
349 | PERROR | ||
350 | ("Invalid single config specified. Only one range for anlog outputs is available.\n"); | ||
351 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
352 | } | ||
353 | |||
354 | if (channel != 0) { | ||
355 | PERROR | ||
356 | ("Invalid channel number specified. Analog output have only one channel.\n"); | ||
357 | return ME_ERRNO_INVALID_CHANNEL; | ||
358 | } | ||
359 | |||
360 | ME_SUBDEVICE_ENTER; | ||
361 | |||
362 | //Subdevice running in stream mode! | ||
363 | if ((instance->status >= ao_status_stream_run_wait) | ||
364 | && (instance->status < ao_status_stream_end)) { | ||
365 | PERROR("Subdevice is busy.\n"); | ||
366 | ME_SUBDEVICE_EXIT; | ||
367 | |||
368 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
369 | } | ||
370 | /// @note For single all calls (config and write) are erasing previous state! | ||
371 | |||
372 | instance->status = ao_status_none; | ||
373 | |||
374 | // Correct single mirrors | ||
375 | instance->single_value_in_fifo = instance->single_value; | ||
376 | |||
377 | //Stop device | ||
378 | err = ao_stop_immediately(instance); | ||
379 | if (err) { | ||
380 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
381 | ME_SUBDEVICE_EXIT; | ||
382 | |||
383 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
384 | } | ||
385 | // Set control register. | ||
386 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
387 | // Set stop bit. Stop streaming mode. | ||
388 | ctrl = inl(instance->ctrl_reg); | ||
389 | //Reset all bits. | ||
390 | ctrl = ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP; | ||
391 | |||
392 | if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) { | ||
393 | PINFO("External digital trigger.\n"); | ||
394 | |||
395 | if (trig_edge == ME_TRIG_EDGE_ANY) { | ||
396 | // ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
397 | instance->ctrl_trg = | ||
398 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
399 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
400 | } else if (trig_edge == ME_TRIG_EDGE_FALLING) { | ||
401 | // ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
402 | instance->ctrl_trg = ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
403 | } else if (trig_edge == ME_TRIG_EDGE_RISING) { | ||
404 | instance->ctrl_trg = 0x0; | ||
405 | } | ||
406 | } else if (trig_type == ME_TRIG_TYPE_SW) { | ||
407 | PDEBUG("Software trigger\n"); | ||
408 | instance->ctrl_trg = 0x0; | ||
409 | } | ||
410 | |||
411 | outl(ctrl, instance->ctrl_reg); | ||
412 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
413 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
414 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
415 | |||
416 | // Set preload/synchronization register. | ||
417 | spin_lock(instance->preload_reg_lock); | ||
418 | if (trig_type == ME_TRIG_TYPE_SW) { | ||
419 | *instance->preload_flags &= | ||
420 | ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx); | ||
421 | } else //if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) | ||
422 | { | ||
423 | *instance->preload_flags |= | ||
424 | ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx; | ||
425 | } | ||
426 | |||
427 | if (trig_chan == ME_TRIG_CHAN_DEFAULT) { | ||
428 | *instance->preload_flags &= | ||
429 | ~(ME4600_AO_SYNC_HOLD << instance->ao_idx); | ||
430 | } else //if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS) | ||
431 | { | ||
432 | *instance->preload_flags |= | ||
433 | ME4600_AO_SYNC_HOLD << instance->ao_idx; | ||
434 | } | ||
435 | |||
436 | //Reset hardware register | ||
437 | sync = inl(instance->preload_reg); | ||
438 | PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
439 | instance->preload_reg - instance->reg_base, sync); | ||
440 | sync &= ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx); | ||
441 | sync |= ME4600_AO_SYNC_HOLD << instance->ao_idx; | ||
442 | |||
443 | //Output configured in default (safe) mode. | ||
444 | outl(sync, instance->preload_reg); | ||
445 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
446 | instance->preload_reg - instance->reg_base, sync); | ||
447 | spin_unlock(instance->preload_reg_lock); | ||
448 | |||
449 | instance->status = ao_status_single_configured; | ||
450 | |||
451 | ME_SUBDEVICE_EXIT; | ||
452 | |||
453 | return err; | ||
454 | } | ||
455 | |||
456 | static int me4600_ao_io_single_read(me_subdevice_t *subdevice, | ||
457 | struct file *filep, | ||
458 | int channel, | ||
459 | int *value, int time_out, int flags) | ||
460 | { | ||
461 | me4600_ao_subdevice_t *instance; | ||
462 | int err = ME_ERRNO_SUCCESS; | ||
463 | |||
464 | unsigned long j; | ||
465 | unsigned long delay = 0; | ||
466 | |||
467 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
468 | |||
469 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
470 | |||
471 | if (flags & ~ME_IO_SINGLE_NONBLOCKING) { | ||
472 | PERROR("Invalid flag specified. %d\n", flags); | ||
473 | return ME_ERRNO_INVALID_FLAGS; | ||
474 | } | ||
475 | |||
476 | if (time_out < 0) { | ||
477 | PERROR("Invalid timeout specified.\n"); | ||
478 | return ME_ERRNO_INVALID_TIMEOUT; | ||
479 | } | ||
480 | |||
481 | if (channel != 0) { | ||
482 | PERROR("Invalid channel number specified.\n"); | ||
483 | return ME_ERRNO_INVALID_CHANNEL; | ||
484 | } | ||
485 | |||
486 | if ((instance->status >= ao_status_stream_configured) | ||
487 | && (instance->status <= ao_status_stream_end)) { | ||
488 | PERROR("Subdevice not configured to work in single mode!\n"); | ||
489 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
490 | } | ||
491 | |||
492 | ME_SUBDEVICE_ENTER; | ||
493 | if ((!flags) && (instance->status == ao_status_single_run_wait)) { //Blocking mode. Wait for trigger. | ||
494 | if (time_out) { | ||
495 | delay = (time_out * HZ) / 1000; | ||
496 | if (delay == 0) | ||
497 | delay = 1; | ||
498 | } | ||
499 | |||
500 | j = jiffies; | ||
501 | |||
502 | //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. | ||
503 | wait_event_interruptible_timeout(instance->wait_queue, | ||
504 | (instance->status != | ||
505 | ao_status_single_run_wait), | ||
506 | (delay) ? delay + | ||
507 | 1 : LONG_MAX); | ||
508 | |||
509 | if (instance->status == ao_status_none) { | ||
510 | PDEBUG("Single canceled.\n"); | ||
511 | err = ME_ERRNO_CANCELLED; | ||
512 | } | ||
513 | |||
514 | if (signal_pending(current)) { | ||
515 | PERROR("Wait on start of state machine interrupted.\n"); | ||
516 | instance->status = ao_status_none; | ||
517 | ao_stop_immediately(instance); | ||
518 | err = ME_ERRNO_SIGNAL; | ||
519 | } | ||
520 | |||
521 | if ((delay) && ((jiffies - j) >= delay)) { | ||
522 | |||
523 | PDEBUG("Timeout reached.\n"); | ||
524 | err = ME_ERRNO_TIMEOUT; | ||
525 | } | ||
526 | |||
527 | *value = | ||
528 | (!err) ? instance->single_value_in_fifo : instance-> | ||
529 | single_value; | ||
530 | } else { //Non-blocking mode | ||
531 | //Read value | ||
532 | *value = instance->single_value; | ||
533 | } | ||
534 | |||
535 | ME_SUBDEVICE_EXIT; | ||
536 | |||
537 | return err; | ||
538 | } | ||
539 | |||
540 | static int me4600_ao_io_single_write(me_subdevice_t *subdevice, | ||
541 | struct file *filep, | ||
542 | int channel, | ||
543 | int value, int time_out, int flags) | ||
544 | { | ||
545 | me4600_ao_subdevice_t *instance; | ||
546 | int err = ME_ERRNO_SUCCESS; | ||
547 | unsigned long cpu_flags; | ||
548 | unsigned long j; | ||
549 | unsigned long delay = 0x0; | ||
550 | |||
551 | //Registry handling variables. | ||
552 | uint32_t sync_mask; | ||
553 | uint32_t mode; | ||
554 | uint32_t tmp; | ||
555 | uint32_t ctrl; | ||
556 | uint32_t status; | ||
557 | |||
558 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
559 | |||
560 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
561 | |||
562 | if (flags & | ||
563 | ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS | | ||
564 | ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { | ||
565 | PERROR("Invalid flag specified.\n"); | ||
566 | return ME_ERRNO_INVALID_FLAGS; | ||
567 | } | ||
568 | |||
569 | if (time_out < 0) { | ||
570 | PERROR("Invalid timeout specified.\n"); | ||
571 | return ME_ERRNO_INVALID_TIMEOUT; | ||
572 | } | ||
573 | |||
574 | if (value & ~ME4600_AO_MAX_DATA) { | ||
575 | PERROR("Invalid value provided.\n"); | ||
576 | return ME_ERRNO_VALUE_OUT_OF_RANGE; | ||
577 | } | ||
578 | |||
579 | if (channel != 0) { | ||
580 | PERROR("Invalid channel number specified.\n"); | ||
581 | return ME_ERRNO_INVALID_CHANNEL; | ||
582 | } | ||
583 | |||
584 | if ((instance->status == ao_status_none) | ||
585 | || (instance->status > ao_status_single_end)) { | ||
586 | PERROR("Subdevice not configured to work in single mode!\n"); | ||
587 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
588 | } | ||
589 | |||
590 | ME_SUBDEVICE_ENTER; | ||
591 | |||
592 | /// @note For single all calls (config and write) are erasing previous state! | ||
593 | |||
594 | //Cancel control task | ||
595 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
596 | instance->ao_control_task_flag = 0; | ||
597 | cancel_delayed_work(&instance->ao_control_task); | ||
598 | |||
599 | // Correct single mirrors | ||
600 | instance->single_value_in_fifo = instance->single_value; | ||
601 | |||
602 | //Stop device | ||
603 | err = ao_stop_immediately(instance); | ||
604 | if (err) { | ||
605 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
606 | ME_SUBDEVICE_EXIT; | ||
607 | |||
608 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
609 | } | ||
610 | |||
611 | if (time_out) { | ||
612 | delay = (time_out * HZ) / 1000; | ||
613 | |||
614 | if (delay == 0) | ||
615 | delay = 1; | ||
616 | } | ||
617 | |||
618 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
619 | |||
620 | instance->single_value_in_fifo = value; | ||
621 | |||
622 | ctrl = inl(instance->ctrl_reg); | ||
623 | |||
624 | if (!instance->fifo) { //No FIFO | ||
625 | //Set the single mode. | ||
626 | ctrl &= ~ME4600_AO_CTRL_MODE_MASK; | ||
627 | |||
628 | //Write value | ||
629 | PDEBUG("Write value\n"); | ||
630 | outl(value, instance->single_reg); | ||
631 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
632 | instance->reg_base, | ||
633 | instance->single_reg - instance->reg_base, value); | ||
634 | } else { // mix-mode | ||
635 | //Set speed | ||
636 | outl(ME4600_AO_MIN_CHAN_TICKS - 1, instance->timer_reg); | ||
637 | PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
638 | instance->reg_base, | ||
639 | instance->timer_reg - instance->reg_base, | ||
640 | (int)ME4600_AO_MIN_CHAN_TICKS); | ||
641 | instance->hardware_stop_delay = HZ / 10; //100ms | ||
642 | |||
643 | status = inl(instance->status_reg); | ||
644 | |||
645 | //Set the continous mode. | ||
646 | ctrl &= ~ME4600_AO_CTRL_MODE_MASK; | ||
647 | ctrl |= ME4600_AO_MODE_CONTINUOUS; | ||
648 | |||
649 | //Prepare FIFO | ||
650 | if (!(ctrl & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. | ||
651 | PINFO("Enableing FIFO.\n"); | ||
652 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
653 | ctrl |= | ||
654 | ME4600_AO_CTRL_BIT_ENABLE_FIFO | | ||
655 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
656 | } else { //Check if FIFO is empty | ||
657 | if (status & ME4600_AO_STATUS_BIT_EF) { //FIFO not empty | ||
658 | PINFO("Reseting FIFO.\n"); | ||
659 | ctrl &= | ||
660 | ~(ME4600_AO_CTRL_BIT_ENABLE_FIFO | | ||
661 | ME4600_AO_CTRL_BIT_ENABLE_IRQ); | ||
662 | ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
663 | outl(ctrl, instance->ctrl_reg); | ||
664 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
665 | instance->reg_base, | ||
666 | instance->ctrl_reg - | ||
667 | instance->reg_base, ctrl); | ||
668 | |||
669 | ctrl |= | ||
670 | ME4600_AO_CTRL_BIT_ENABLE_FIFO | | ||
671 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
672 | } else { //FIFO empty, only interrupt needs to be disabled! | ||
673 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
674 | ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
675 | } | ||
676 | } | ||
677 | |||
678 | outl(ctrl, instance->ctrl_reg); | ||
679 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
680 | instance->reg_base, | ||
681 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
682 | |||
683 | //Write output - 1 value to FIFO | ||
684 | if (instance->ao_idx & 0x1) { | ||
685 | outl(value <<= 16, instance->fifo_reg); | ||
686 | PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
687 | instance->reg_base, | ||
688 | instance->fifo_reg - instance->reg_base, | ||
689 | value <<= 16); | ||
690 | } else { | ||
691 | outl(value, instance->fifo_reg); | ||
692 | PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
693 | instance->reg_base, | ||
694 | instance->fifo_reg - instance->reg_base, | ||
695 | value); | ||
696 | } | ||
697 | } | ||
698 | |||
699 | mode = *instance->preload_flags >> instance->ao_idx; | ||
700 | mode &= (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG); | ||
701 | |||
702 | PINFO("Triggering mode: 0x%x\n", mode); | ||
703 | |||
704 | spin_lock(instance->preload_reg_lock); | ||
705 | sync_mask = inl(instance->preload_reg); | ||
706 | PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
707 | instance->preload_reg - instance->reg_base, sync_mask); | ||
708 | switch (mode) { | ||
709 | case 0: //Individual software | ||
710 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
711 | |||
712 | if (!instance->fifo) { // No FIFO - In this case resetting 'ME4600_AO_SYNC_HOLD' will trigger output. | ||
713 | 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. | ||
714 | sync_mask &= | ||
715 | ~(ME4600_AO_SYNC_EXT_TRIG << instance-> | ||
716 | ao_idx); | ||
717 | sync_mask |= | ||
718 | ME4600_AO_SYNC_HOLD << instance->ao_idx; | ||
719 | |||
720 | outl(sync_mask, instance->preload_reg); | ||
721 | PDEBUG_REG | ||
722 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
723 | instance->reg_base, | ||
724 | instance->preload_reg - instance->reg_base, | ||
725 | sync_mask); | ||
726 | } | ||
727 | } else { // FIFO | ||
728 | if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. | ||
729 | sync_mask &= | ||
730 | ~((ME4600_AO_SYNC_EXT_TRIG | | ||
731 | ME4600_AO_SYNC_HOLD) << instance-> | ||
732 | ao_idx); | ||
733 | |||
734 | outl(sync_mask, instance->preload_reg); | ||
735 | PDEBUG_REG | ||
736 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
737 | instance->reg_base, | ||
738 | instance->preload_reg - instance->reg_base, | ||
739 | sync_mask); | ||
740 | } | ||
741 | } | ||
742 | instance->single_value = value; | ||
743 | break; | ||
744 | |||
745 | case ME4600_AO_SYNC_EXT_TRIG: //Individual hardware | ||
746 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
747 | |||
748 | if (!instance->fifo) { // No FIFO - In this case resetting 'ME4600_AO_SYNC_HOLD' will trigger output. | ||
749 | 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 | ||
750 | sync_mask &= | ||
751 | ~(ME4600_AO_SYNC_EXT_TRIG << instance-> | ||
752 | ao_idx); | ||
753 | sync_mask |= | ||
754 | ME4600_AO_SYNC_HOLD << instance->ao_idx; | ||
755 | |||
756 | outl(sync_mask, instance->preload_reg); | ||
757 | PDEBUG_REG | ||
758 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
759 | instance->reg_base, | ||
760 | instance->preload_reg - instance->reg_base, | ||
761 | sync_mask); | ||
762 | } | ||
763 | } else { // FIFO | ||
764 | if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. | ||
765 | sync_mask &= | ||
766 | ~((ME4600_AO_SYNC_EXT_TRIG | | ||
767 | ME4600_AO_SYNC_HOLD) << instance-> | ||
768 | ao_idx); | ||
769 | |||
770 | outl(sync_mask, instance->preload_reg); | ||
771 | PDEBUG_REG | ||
772 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
773 | instance->reg_base, | ||
774 | instance->preload_reg - instance->reg_base, | ||
775 | sync_mask); | ||
776 | } | ||
777 | } | ||
778 | break; | ||
779 | |||
780 | case ME4600_AO_SYNC_HOLD: //Synchronous software | ||
781 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
782 | |||
783 | // if((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME4600_AO_SYNC_HOLD) | ||
784 | 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 | ||
785 | sync_mask |= | ||
786 | ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx; | ||
787 | // sync_mask &= ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx); | ||
788 | sync_mask |= ME4600_AO_SYNC_HOLD << instance->ao_idx; | ||
789 | |||
790 | outl(sync_mask, instance->preload_reg); | ||
791 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
792 | instance->reg_base, | ||
793 | instance->preload_reg - instance->reg_base, | ||
794 | sync_mask); | ||
795 | } | ||
796 | break; | ||
797 | |||
798 | case (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG): //Synchronous hardware | ||
799 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
800 | 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 | ||
801 | sync_mask |= | ||
802 | (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << | ||
803 | instance->ao_idx; | ||
804 | |||
805 | outl(sync_mask, instance->preload_reg); | ||
806 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
807 | instance->reg_base, | ||
808 | instance->preload_reg - instance->reg_base, | ||
809 | sync_mask); | ||
810 | } | ||
811 | break; | ||
812 | } | ||
813 | // spin_unlock(instance->preload_reg_lock); // Moved down. | ||
814 | |||
815 | //Activate ISM (remove 'stop' bits) | ||
816 | ctrl &= | ||
817 | ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
818 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); | ||
819 | ctrl |= instance->ctrl_trg; | ||
820 | ctrl &= ~(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
821 | outl(ctrl, instance->ctrl_reg); | ||
822 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
823 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
824 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
825 | |||
826 | /// @note When flag 'ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS' is set than output is triggered. ALWAYS! | ||
827 | |||
828 | if (!instance->fifo) { //No FIFO | ||
829 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Fired all software synchronous outputs. | ||
830 | tmp = ~(*instance->preload_flags | 0xFFFF0000); | ||
831 | PINFO | ||
832 | ("Fired all software synchronous outputs. mask:0x%08x\n", | ||
833 | tmp); | ||
834 | tmp |= sync_mask & 0xFFFF0000; | ||
835 | // Add this channel to list | ||
836 | tmp &= ~(ME4600_AO_SYNC_HOLD << instance->ao_idx); | ||
837 | |||
838 | //Fire | ||
839 | PINFO("Software trigger.\n"); | ||
840 | outl(tmp, instance->preload_reg); | ||
841 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
842 | instance->reg_base, | ||
843 | instance->preload_reg - instance->reg_base, | ||
844 | tmp); | ||
845 | |||
846 | //Restore save settings | ||
847 | outl(sync_mask, instance->preload_reg); | ||
848 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
849 | instance->reg_base, | ||
850 | instance->preload_reg - instance->reg_base, | ||
851 | sync_mask); | ||
852 | } else if (!mode) { // Add this channel to list | ||
853 | outl(sync_mask & | ||
854 | ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), | ||
855 | instance->preload_reg); | ||
856 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
857 | instance->reg_base, | ||
858 | instance->preload_reg - instance->reg_base, | ||
859 | sync_mask & ~(ME4600_AO_SYNC_HOLD << | ||
860 | instance->ao_idx)); | ||
861 | |||
862 | //Fire | ||
863 | PINFO("Software trigger.\n"); | ||
864 | |||
865 | //Restore save settings | ||
866 | outl(sync_mask, instance->preload_reg); | ||
867 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
868 | instance->reg_base, | ||
869 | instance->preload_reg - instance->reg_base, | ||
870 | sync_mask); | ||
871 | } | ||
872 | |||
873 | } else { // mix-mode - begin | ||
874 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs | ||
875 | //Add channel to start list | ||
876 | outl(sync_mask | | ||
877 | (ME4600_AO_SYNC_HOLD << instance->ao_idx), | ||
878 | instance->preload_reg); | ||
879 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
880 | instance->reg_base, | ||
881 | instance->preload_reg - instance->reg_base, | ||
882 | sync_mask | (ME4600_AO_SYNC_HOLD << | ||
883 | instance->ao_idx)); | ||
884 | |||
885 | //Fire | ||
886 | PINFO | ||
887 | ("Fired all software synchronous outputs by software trigger.\n"); | ||
888 | outl(0x8000, instance->single_reg); | ||
889 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
890 | instance->reg_base, | ||
891 | instance->single_reg - instance->reg_base, | ||
892 | 0x8000); | ||
893 | |||
894 | //Restore save settings | ||
895 | outl(sync_mask, instance->preload_reg); | ||
896 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
897 | instance->reg_base, | ||
898 | instance->preload_reg - instance->reg_base, | ||
899 | sync_mask); | ||
900 | } else if (!mode) { //Trigger outputs | ||
901 | /* //Remove channel from start list //<== Unnecessary. Removed. | ||
902 | outl(sync_mask & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); | ||
903 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, tmp); | ||
904 | */ | ||
905 | //Fire | ||
906 | PINFO("Software trigger.\n"); | ||
907 | outl(0x8000, instance->single_reg); | ||
908 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
909 | instance->reg_base, | ||
910 | instance->single_reg - instance->reg_base, | ||
911 | 0x8000); | ||
912 | |||
913 | /* //Restore save settings //<== Unnecessary. Removed. | ||
914 | outl(sync_mask, instance->preload_reg); | ||
915 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask); | ||
916 | */ | ||
917 | } | ||
918 | } | ||
919 | spin_unlock(instance->preload_reg_lock); | ||
920 | |||
921 | j = jiffies; | ||
922 | instance->status = ao_status_single_run_wait; | ||
923 | |||
924 | instance->timeout.delay = delay; | ||
925 | instance->timeout.start_time = j; | ||
926 | instance->ao_control_task_flag = 1; | ||
927 | queue_delayed_work(instance->me4600_workqueue, | ||
928 | &instance->ao_control_task, 1); | ||
929 | |||
930 | if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { | ||
931 | |||
932 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
933 | wait_event_interruptible_timeout(instance->wait_queue, | ||
934 | (instance->status != | ||
935 | ao_status_single_run_wait), | ||
936 | (delay) ? delay + | ||
937 | 1 : LONG_MAX); | ||
938 | |||
939 | if (((!delay) || ((jiffies - j) <= delay)) | ||
940 | && (instance->status != ao_status_single_end)) { | ||
941 | PDEBUG("Single canceled.\n"); | ||
942 | err = ME_ERRNO_CANCELLED; | ||
943 | } | ||
944 | |||
945 | if (signal_pending(current)) { | ||
946 | PERROR("Wait on start of state machine interrupted.\n"); | ||
947 | instance->ao_control_task_flag = 0; | ||
948 | cancel_delayed_work(&instance->ao_control_task); | ||
949 | ao_stop_immediately(instance); | ||
950 | instance->status = ao_status_none; | ||
951 | err = ME_ERRNO_SIGNAL; | ||
952 | } | ||
953 | |||
954 | if ((delay) && ((jiffies - j) >= delay)) { | ||
955 | if (instance->status == ao_status_single_end) { | ||
956 | PDEBUG("Timeout reached.\n"); | ||
957 | } else { | ||
958 | if ((jiffies - j) > delay) { | ||
959 | PERROR | ||
960 | ("Timeout reached. Not handled by control task!\n"); | ||
961 | } else { | ||
962 | PERROR | ||
963 | ("Timeout reached. Signal come but status is strange: %d\n", | ||
964 | instance->status); | ||
965 | } | ||
966 | |||
967 | ao_stop_immediately(instance); | ||
968 | } | ||
969 | |||
970 | instance->ao_control_task_flag = 0; | ||
971 | cancel_delayed_work(&instance->ao_control_task); | ||
972 | instance->status = ao_status_single_end; | ||
973 | err = ME_ERRNO_TIMEOUT; | ||
974 | } | ||
975 | } | ||
976 | |||
977 | ME_SUBDEVICE_EXIT; | ||
978 | |||
979 | return err; | ||
980 | } | ||
981 | |||
982 | static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, | ||
983 | struct file *filep, | ||
984 | meIOStreamConfig_t *config_list, | ||
985 | int count, | ||
986 | meIOStreamTrigger_t *trigger, | ||
987 | int fifo_irq_threshold, int flags) | ||
988 | { | ||
989 | me4600_ao_subdevice_t *instance; | ||
990 | int err = ME_ERRNO_SUCCESS; | ||
991 | uint32_t ctrl; | ||
992 | unsigned long cpu_flags; | ||
993 | uint64_t conv_ticks; | ||
994 | unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; | ||
995 | unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; | ||
996 | |||
997 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
998 | |||
999 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1000 | |||
1001 | if (!instance->fifo) { | ||
1002 | PERROR("Not a streaming ao.\n"); | ||
1003 | return ME_ERRNO_NOT_SUPPORTED; | ||
1004 | } | ||
1005 | |||
1006 | conv_ticks = | ||
1007 | (uint64_t) conv_start_ticks_low + | ||
1008 | ((uint64_t) conv_start_ticks_high << 32); | ||
1009 | |||
1010 | if (flags & | ||
1011 | ~(ME_IO_STREAM_CONFIG_HARDWARE_ONLY | ME_IO_STREAM_CONFIG_WRAPAROUND | ||
1012 | | ME_IO_STREAM_CONFIG_BIT_PATTERN)) { | ||
1013 | PERROR("Invalid flags.\n"); | ||
1014 | return ME_ERRNO_INVALID_FLAGS; | ||
1015 | } | ||
1016 | |||
1017 | if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { | ||
1018 | if (!(flags & ME_IO_STREAM_CONFIG_WRAPAROUND)) { | ||
1019 | PERROR | ||
1020 | ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n"); | ||
1021 | return ME_ERRNO_INVALID_FLAGS; | ||
1022 | } | ||
1023 | |||
1024 | if ((trigger->iAcqStopTrigType != ME_TRIG_TYPE_NONE) | ||
1025 | || (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE)) { | ||
1026 | PERROR | ||
1027 | ("Hardware wraparound mode must be in infinite mode.\n"); | ||
1028 | return ME_ERRNO_INVALID_FLAGS; | ||
1029 | } | ||
1030 | } | ||
1031 | |||
1032 | if (count != 1) { | ||
1033 | PERROR("Only 1 entry in config list acceptable.\n"); | ||
1034 | return ME_ERRNO_INVALID_CONFIG_LIST_COUNT; | ||
1035 | } | ||
1036 | |||
1037 | if (config_list[0].iChannel != 0) { | ||
1038 | PERROR("Invalid channel number specified.\n"); | ||
1039 | return ME_ERRNO_INVALID_CHANNEL; | ||
1040 | } | ||
1041 | |||
1042 | if (config_list[0].iStreamConfig != 0) { | ||
1043 | PERROR("Only one range available.\n"); | ||
1044 | return ME_ERRNO_INVALID_STREAM_CONFIG; | ||
1045 | } | ||
1046 | |||
1047 | if (config_list[0].iRef != ME_REF_AO_GROUND) { | ||
1048 | PERROR("Output is referenced to ground.\n"); | ||
1049 | return ME_ERRNO_INVALID_REF; | ||
1050 | } | ||
1051 | |||
1052 | if ((trigger->iAcqStartTicksLow != 0) | ||
1053 | || (trigger->iAcqStartTicksHigh != 0)) { | ||
1054 | PERROR | ||
1055 | ("Invalid acquisition start trigger argument specified.\n"); | ||
1056 | return ME_ERRNO_INVALID_ACQ_START_ARG; | ||
1057 | } | ||
1058 | |||
1059 | if (config_list[0].iFlags) { | ||
1060 | PERROR("Invalid config list flag.\n"); | ||
1061 | return ME_ERRNO_INVALID_FLAGS; | ||
1062 | } | ||
1063 | |||
1064 | switch (trigger->iAcqStartTrigType) { | ||
1065 | case ME_TRIG_TYPE_SW: | ||
1066 | if (trigger->iAcqStartTrigEdge != ME_TRIG_EDGE_NONE) { | ||
1067 | PERROR | ||
1068 | ("Invalid acquisition start trigger edge specified.\n"); | ||
1069 | return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
1070 | } | ||
1071 | break; | ||
1072 | |||
1073 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
1074 | switch (trigger->iAcqStartTrigEdge) { | ||
1075 | case ME_TRIG_EDGE_ANY: | ||
1076 | case ME_TRIG_EDGE_RISING: | ||
1077 | case ME_TRIG_EDGE_FALLING: | ||
1078 | break; | ||
1079 | |||
1080 | default: | ||
1081 | PERROR | ||
1082 | ("Invalid acquisition start trigger edge specified.\n"); | ||
1083 | return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
1084 | } | ||
1085 | break; | ||
1086 | |||
1087 | default: | ||
1088 | PERROR("Invalid acquisition start trigger type specified.\n"); | ||
1089 | return ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; | ||
1090 | } | ||
1091 | |||
1092 | if (trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) { | ||
1093 | PERROR("Invalid scan start trigger type specified.\n"); | ||
1094 | return ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; | ||
1095 | } | ||
1096 | |||
1097 | if (trigger->iConvStartTrigType != ME_TRIG_TYPE_TIMER) { | ||
1098 | PERROR("Invalid conv start trigger type specified.\n"); | ||
1099 | return ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; | ||
1100 | } | ||
1101 | |||
1102 | if ((conv_ticks < ME4600_AO_MIN_CHAN_TICKS) | ||
1103 | || (conv_ticks > ME4600_AO_MAX_CHAN_TICKS)) { | ||
1104 | PERROR("Invalid conv start trigger argument specified.\n"); | ||
1105 | return ME_ERRNO_INVALID_CONV_START_ARG; | ||
1106 | } | ||
1107 | |||
1108 | if (trigger->iAcqStartTicksLow || trigger->iAcqStartTicksHigh) { | ||
1109 | PERROR("Invalid acq start trigger argument specified.\n"); | ||
1110 | return ME_ERRNO_INVALID_ACQ_START_ARG; | ||
1111 | } | ||
1112 | |||
1113 | if (trigger->iScanStartTicksLow || trigger->iScanStartTicksHigh) { | ||
1114 | PERROR("Invalid scan start trigger argument specified.\n"); | ||
1115 | return ME_ERRNO_INVALID_SCAN_START_ARG; | ||
1116 | } | ||
1117 | |||
1118 | switch (trigger->iScanStopTrigType) { | ||
1119 | case ME_TRIG_TYPE_NONE: | ||
1120 | if (trigger->iScanStopCount != 0) { | ||
1121 | PERROR("Invalid scan stop count specified.\n"); | ||
1122 | return ME_ERRNO_INVALID_SCAN_STOP_ARG; | ||
1123 | } | ||
1124 | break; | ||
1125 | |||
1126 | case ME_TRIG_TYPE_COUNT: | ||
1127 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
1128 | if (trigger->iScanStopCount <= 0) { | ||
1129 | PERROR("Invalid scan stop count specified.\n"); | ||
1130 | return ME_ERRNO_INVALID_SCAN_STOP_ARG; | ||
1131 | } | ||
1132 | } else { | ||
1133 | PERROR("The continous mode has not 'scan' contects.\n"); | ||
1134 | return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1135 | } | ||
1136 | break; | ||
1137 | |||
1138 | default: | ||
1139 | PERROR("Invalid scan stop trigger type specified.\n"); | ||
1140 | return ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; | ||
1141 | } | ||
1142 | |||
1143 | switch (trigger->iAcqStopTrigType) { | ||
1144 | case ME_TRIG_TYPE_NONE: | ||
1145 | if (trigger->iAcqStopCount != 0) { | ||
1146 | PERROR("Invalid acq stop count specified.\n"); | ||
1147 | return ME_ERRNO_INVALID_ACQ_STOP_ARG; | ||
1148 | } | ||
1149 | break; | ||
1150 | |||
1151 | case ME_TRIG_TYPE_COUNT: | ||
1152 | if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { | ||
1153 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1154 | return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1155 | } | ||
1156 | |||
1157 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
1158 | if (trigger->iAcqStopCount <= 0) { | ||
1159 | PERROR | ||
1160 | ("The continous mode has not 'scan' contects.\n"); | ||
1161 | return ME_ERRNO_INVALID_ACQ_STOP_ARG; | ||
1162 | } | ||
1163 | } | ||
1164 | break; | ||
1165 | |||
1166 | default: | ||
1167 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1168 | return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1169 | } | ||
1170 | |||
1171 | switch (trigger->iAcqStartTrigChan) { | ||
1172 | case ME_TRIG_CHAN_DEFAULT: | ||
1173 | case ME_TRIG_CHAN_SYNCHRONOUS: | ||
1174 | break; | ||
1175 | |||
1176 | default: | ||
1177 | PERROR("Invalid acq start trigger channel specified.\n"); | ||
1178 | return ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; | ||
1179 | } | ||
1180 | |||
1181 | ME_SUBDEVICE_ENTER; | ||
1182 | |||
1183 | if ((flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) && !instance->bitpattern) { | ||
1184 | PERROR("This subdevice not support output redirection.\n"); | ||
1185 | ME_SUBDEVICE_EXIT; | ||
1186 | return ME_ERRNO_INVALID_FLAGS; | ||
1187 | } | ||
1188 | //Stop device | ||
1189 | |||
1190 | //Cancel control task | ||
1191 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
1192 | instance->ao_control_task_flag = 0; | ||
1193 | cancel_delayed_work(&instance->ao_control_task); | ||
1194 | |||
1195 | //Check if state machine is stopped. | ||
1196 | err = ao_stop_immediately(instance); | ||
1197 | if (err) { | ||
1198 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
1199 | ME_SUBDEVICE_EXIT; | ||
1200 | |||
1201 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
1202 | } | ||
1203 | |||
1204 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1205 | //Reset control register. Block all actions. Disable IRQ. Disable FIFO. | ||
1206 | ctrl = | ||
1207 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP | | ||
1208 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
1209 | outl(ctrl, instance->ctrl_reg); | ||
1210 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1211 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1212 | |||
1213 | //This is paranoic, but to be sure. | ||
1214 | instance->preloaded_count = 0; | ||
1215 | instance->data_count = 0; | ||
1216 | instance->circ_buf.head = 0; | ||
1217 | instance->circ_buf.tail = 0; | ||
1218 | |||
1219 | /* Set mode. */ | ||
1220 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { //Wraparound | ||
1221 | if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { //Hardware wraparound | ||
1222 | PINFO("Hardware wraparound.\n"); | ||
1223 | ctrl |= ME4600_AO_MODE_WRAPAROUND; | ||
1224 | instance->mode = ME4600_AO_HW_WRAP_MODE; | ||
1225 | } else { //Software wraparound | ||
1226 | PINFO("Software wraparound.\n"); | ||
1227 | ctrl |= ME4600_AO_MODE_CONTINUOUS; | ||
1228 | instance->mode = ME4600_AO_SW_WRAP_MODE; | ||
1229 | } | ||
1230 | } else { //Continous | ||
1231 | PINFO("Continous.\n"); | ||
1232 | ctrl |= ME4600_AO_MODE_CONTINUOUS; | ||
1233 | instance->mode = ME4600_AO_CONTINOUS; | ||
1234 | } | ||
1235 | |||
1236 | //Set the trigger edge. | ||
1237 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Set the trigger type and edge for external trigger. | ||
1238 | PINFO("External digital trigger.\n"); | ||
1239 | instance->start_mode = ME4600_AO_EXT_TRIG; | ||
1240 | /* | ||
1241 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
1242 | */ | ||
1243 | switch (trigger->iAcqStartTrigEdge) { | ||
1244 | case ME_TRIG_EDGE_RISING: | ||
1245 | PINFO("Set the trigger edge: rising.\n"); | ||
1246 | instance->ctrl_trg = 0x0; | ||
1247 | break; | ||
1248 | |||
1249 | case ME_TRIG_EDGE_FALLING: | ||
1250 | PINFO("Set the trigger edge: falling.\n"); | ||
1251 | // ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
1252 | instance->ctrl_trg = ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
1253 | break; | ||
1254 | |||
1255 | case ME_TRIG_EDGE_ANY: | ||
1256 | PINFO("Set the trigger edge: both edges.\n"); | ||
1257 | // ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
1258 | instance->ctrl_trg = | ||
1259 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
1260 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
1261 | break; | ||
1262 | } | ||
1263 | } else { | ||
1264 | PINFO("Internal software trigger.\n"); | ||
1265 | instance->start_mode = 0; | ||
1266 | } | ||
1267 | |||
1268 | //Set the stop mode and value. | ||
1269 | if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of data | ||
1270 | instance->stop_mode = ME4600_AO_ACQ_STOP_MODE; | ||
1271 | instance->stop_count = trigger->iAcqStopCount; | ||
1272 | } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of 'scans' | ||
1273 | instance->stop_mode = ME4600_AO_SCAN_STOP_MODE; | ||
1274 | instance->stop_count = trigger->iScanStopCount; | ||
1275 | } else { //Infinite | ||
1276 | instance->stop_mode = ME4600_AO_INF_STOP_MODE; | ||
1277 | instance->stop_count = 0; | ||
1278 | } | ||
1279 | |||
1280 | PINFO("Stop count: %d.\n", instance->stop_count); | ||
1281 | |||
1282 | if (trigger->iAcqStartTrigChan == ME_TRIG_CHAN_SYNCHRONOUS) { //Synchronous start | ||
1283 | instance->start_mode |= ME4600_AO_SYNC_HOLD; | ||
1284 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Externaly triggered | ||
1285 | PINFO("Synchronous start. Externaly trigger active.\n"); | ||
1286 | instance->start_mode |= ME4600_AO_SYNC_EXT_TRIG; | ||
1287 | } | ||
1288 | #ifdef MEDEBUG_INFO | ||
1289 | else { | ||
1290 | PINFO | ||
1291 | ("Synchronous start. Externaly trigger dissabled.\n"); | ||
1292 | } | ||
1293 | #endif | ||
1294 | |||
1295 | } | ||
1296 | //Set speed | ||
1297 | outl(conv_ticks - 2, instance->timer_reg); | ||
1298 | PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%llx\n", instance->reg_base, | ||
1299 | instance->timer_reg - instance->reg_base, conv_ticks - 2); | ||
1300 | instance->hardware_stop_delay = (int)(conv_ticks * HZ) / ME4600_AO_BASE_FREQUENCY; //<== MUST be with cast! | ||
1301 | |||
1302 | //Conect outputs to analog or digital port. | ||
1303 | if (flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) { | ||
1304 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_DO; | ||
1305 | } | ||
1306 | // Write the control word | ||
1307 | outl(ctrl, instance->ctrl_reg); | ||
1308 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1309 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1310 | |||
1311 | //Set status. | ||
1312 | instance->status = ao_status_stream_configured; | ||
1313 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
1314 | |||
1315 | ME_SUBDEVICE_EXIT; | ||
1316 | |||
1317 | return err; | ||
1318 | } | ||
1319 | |||
1320 | static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, | ||
1321 | struct file *filep, | ||
1322 | int time_out, int *count, int flags) | ||
1323 | { | ||
1324 | me4600_ao_subdevice_t *instance; | ||
1325 | int err = ME_ERRNO_SUCCESS; | ||
1326 | long t = 0; | ||
1327 | long j; | ||
1328 | |||
1329 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
1330 | |||
1331 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1332 | |||
1333 | if (!instance->fifo) { | ||
1334 | PERROR("Not a streaming ao.\n"); | ||
1335 | return ME_ERRNO_NOT_SUPPORTED; | ||
1336 | } | ||
1337 | |||
1338 | if (flags) { | ||
1339 | PERROR("Invalid flag specified.\n"); | ||
1340 | return ME_ERRNO_INVALID_FLAGS; | ||
1341 | } | ||
1342 | |||
1343 | if (!instance->circ_buf.buf) { | ||
1344 | PERROR("Circular buffer not exists.\n"); | ||
1345 | return ME_ERRNO_INTERNAL; | ||
1346 | } | ||
1347 | |||
1348 | if (time_out < 0) { | ||
1349 | PERROR("Invalid time_out specified.\n"); | ||
1350 | return ME_ERRNO_INVALID_TIMEOUT; | ||
1351 | } | ||
1352 | |||
1353 | ME_SUBDEVICE_ENTER; | ||
1354 | |||
1355 | if (me_circ_buf_space(&instance->circ_buf)) { //The buffer is NOT full. | ||
1356 | *count = me_circ_buf_space(&instance->circ_buf); | ||
1357 | } else { //The buffer is full. | ||
1358 | if (time_out) { | ||
1359 | t = (time_out * HZ) / 1000; | ||
1360 | |||
1361 | if (t == 0) | ||
1362 | t = 1; | ||
1363 | } else { //Max time. | ||
1364 | t = LONG_MAX; | ||
1365 | } | ||
1366 | |||
1367 | *count = 0; | ||
1368 | |||
1369 | j = jiffies; | ||
1370 | |||
1371 | //Only runing process will interrupt this call. Interrupts are when FIFO HF is signaled. | ||
1372 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1373 | ((me_circ_buf_space | ||
1374 | (&instance->circ_buf)) | ||
1375 | || !(inl(instance->status_reg) | ||
1376 | & | ||
1377 | ME4600_AO_STATUS_BIT_FSM)), | ||
1378 | t); | ||
1379 | |||
1380 | if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { | ||
1381 | PERROR("AO subdevice is not running.\n"); | ||
1382 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
1383 | } else if (signal_pending(current)) { | ||
1384 | PERROR("Wait on values interrupted from signal.\n"); | ||
1385 | instance->status = ao_status_none; | ||
1386 | ao_stop_immediately(instance); | ||
1387 | err = ME_ERRNO_SIGNAL; | ||
1388 | } else if ((jiffies - j) >= t) { | ||
1389 | PERROR("Wait on values timed out.\n"); | ||
1390 | err = ME_ERRNO_TIMEOUT; | ||
1391 | } else { //Uff... all is good. Inform user about empty space. | ||
1392 | *count = me_circ_buf_space(&instance->circ_buf); | ||
1393 | } | ||
1394 | } | ||
1395 | |||
1396 | ME_SUBDEVICE_EXIT; | ||
1397 | |||
1398 | return err; | ||
1399 | } | ||
1400 | |||
1401 | static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, | ||
1402 | struct file *filep, | ||
1403 | int start_mode, int time_out, int flags) | ||
1404 | { | ||
1405 | me4600_ao_subdevice_t *instance; | ||
1406 | int err = ME_ERRNO_SUCCESS; | ||
1407 | unsigned long cpu_flags = 0; | ||
1408 | uint32_t status; | ||
1409 | uint32_t ctrl; | ||
1410 | uint32_t synch; | ||
1411 | int count = 0; | ||
1412 | int circ_buffer_count; | ||
1413 | |||
1414 | unsigned long ref; | ||
1415 | unsigned long delay = 0; | ||
1416 | |||
1417 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
1418 | |||
1419 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1420 | |||
1421 | if (!instance->fifo) { | ||
1422 | PERROR("Not a streaming ao.\n"); | ||
1423 | return ME_ERRNO_NOT_SUPPORTED; | ||
1424 | } | ||
1425 | |||
1426 | if (flags & ~ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { | ||
1427 | PERROR("Invalid flags.\n"); | ||
1428 | return ME_ERRNO_INVALID_FLAGS; | ||
1429 | } | ||
1430 | |||
1431 | if (time_out < 0) { | ||
1432 | PERROR("Invalid timeout specified.\n"); | ||
1433 | return ME_ERRNO_INVALID_TIMEOUT; | ||
1434 | } | ||
1435 | |||
1436 | if ((start_mode != ME_START_MODE_BLOCKING) | ||
1437 | && (start_mode != ME_START_MODE_NONBLOCKING)) { | ||
1438 | PERROR("Invalid start mode specified.\n"); | ||
1439 | return ME_ERRNO_INVALID_START_MODE; | ||
1440 | } | ||
1441 | |||
1442 | if (time_out) { | ||
1443 | delay = (time_out * HZ) / 1000; | ||
1444 | if (delay == 0) | ||
1445 | delay = 1; | ||
1446 | } | ||
1447 | |||
1448 | switch (instance->status) { //Checking actual mode. | ||
1449 | case ao_status_stream_configured: | ||
1450 | case ao_status_stream_end: | ||
1451 | //Correct modes! | ||
1452 | break; | ||
1453 | |||
1454 | //The device is in wrong mode. | ||
1455 | case ao_status_none: | ||
1456 | case ao_status_single_configured: | ||
1457 | case ao_status_single_run_wait: | ||
1458 | case ao_status_single_run: | ||
1459 | case ao_status_single_end_wait: | ||
1460 | PERROR | ||
1461 | ("Subdevice must be preinitialize correctly for streaming.\n"); | ||
1462 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
1463 | |||
1464 | case ao_status_stream_fifo_error: | ||
1465 | case ao_status_stream_buffer_error: | ||
1466 | case ao_status_stream_error: | ||
1467 | PDEBUG("Before restart broke stream 'STOP' must be caled.\n"); | ||
1468 | return ME_STATUS_ERROR; | ||
1469 | |||
1470 | case ao_status_stream_run_wait: | ||
1471 | case ao_status_stream_run: | ||
1472 | case ao_status_stream_end_wait: | ||
1473 | PDEBUG("Stream is already working.\n"); | ||
1474 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
1475 | |||
1476 | default: | ||
1477 | instance->status = ao_status_stream_error; | ||
1478 | PERROR_CRITICAL("Status is in wrong state!\n"); | ||
1479 | return ME_ERRNO_INTERNAL; | ||
1480 | |||
1481 | } | ||
1482 | |||
1483 | ME_SUBDEVICE_ENTER; | ||
1484 | |||
1485 | if (instance->mode == ME4600_AO_CONTINOUS) { //Continous | ||
1486 | instance->circ_buf.tail += instance->preloaded_count; | ||
1487 | instance->circ_buf.tail &= instance->circ_buf.mask; | ||
1488 | } | ||
1489 | circ_buffer_count = me_circ_buf_values(&instance->circ_buf); | ||
1490 | |||
1491 | if (!circ_buffer_count && !instance->preloaded_count) { //No values in buffer | ||
1492 | ME_SUBDEVICE_EXIT; | ||
1493 | PERROR("No values in buffer!\n"); | ||
1494 | return ME_ERRNO_LACK_OF_RESOURCES; | ||
1495 | } | ||
1496 | |||
1497 | //Cancel control task | ||
1498 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
1499 | instance->ao_control_task_flag = 0; | ||
1500 | cancel_delayed_work(&instance->ao_control_task); | ||
1501 | |||
1502 | //Stop device | ||
1503 | err = ao_stop_immediately(instance); | ||
1504 | if (err) { | ||
1505 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
1506 | ME_SUBDEVICE_EXIT; | ||
1507 | |||
1508 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
1509 | } | ||
1510 | //Set values for single_read() | ||
1511 | instance->single_value = ME4600_AO_MAX_DATA + 1; | ||
1512 | instance->single_value_in_fifo = ME4600_AO_MAX_DATA + 1; | ||
1513 | |||
1514 | //Setting stop points | ||
1515 | if (instance->stop_mode == ME4600_AO_SCAN_STOP_MODE) { | ||
1516 | instance->stop_data_count = | ||
1517 | instance->stop_count * circ_buffer_count; | ||
1518 | } else { | ||
1519 | instance->stop_data_count = instance->stop_count; | ||
1520 | } | ||
1521 | |||
1522 | if ((instance->stop_data_count != 0) | ||
1523 | && (instance->stop_data_count < circ_buffer_count)) { | ||
1524 | PERROR("More data in buffer than previously set limit!\n"); | ||
1525 | } | ||
1526 | |||
1527 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1528 | ctrl = inl(instance->ctrl_reg); | ||
1529 | //Check FIFO | ||
1530 | 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 | ||
1531 | PINFO("Enableing FIFO.\n"); | ||
1532 | ctrl |= | ||
1533 | ME4600_AO_CTRL_BIT_ENABLE_FIFO | | ||
1534 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
1535 | |||
1536 | instance->preloaded_count = 0; | ||
1537 | instance->data_count = 0; | ||
1538 | } else { //Block IRQ | ||
1539 | ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
1540 | } | ||
1541 | outl(ctrl, instance->ctrl_reg); | ||
1542 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1543 | instance->ctrl_reg - instance->reg_base, | ||
1544 | ctrl | ME4600_AO_CTRL_BIT_RESET_IRQ); | ||
1545 | |||
1546 | //Fill FIFO <= Generaly this should be done by user pre-load call but this is second place to do it. | ||
1547 | status = inl(instance->status_reg); | ||
1548 | if (!(status & ME4600_AO_STATUS_BIT_EF)) { //FIFO empty | ||
1549 | if (instance->stop_data_count == 0) { | ||
1550 | count = ME4600_AO_FIFO_COUNT; | ||
1551 | } else { | ||
1552 | count = | ||
1553 | (ME4600_AO_FIFO_COUNT < | ||
1554 | instance-> | ||
1555 | stop_data_count) ? ME4600_AO_FIFO_COUNT : | ||
1556 | instance->stop_data_count; | ||
1557 | } | ||
1558 | |||
1559 | //Copy data | ||
1560 | count = | ||
1561 | ao_write_data(instance, count, instance->preloaded_count); | ||
1562 | |||
1563 | if (count < 0) { //This should never happend! | ||
1564 | PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); | ||
1565 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
1566 | cpu_flags); | ||
1567 | ME_SUBDEVICE_EXIT; | ||
1568 | return ME_ERRNO_INTERNAL; | ||
1569 | } | ||
1570 | } | ||
1571 | //Set pre-load features. | ||
1572 | spin_lock(instance->preload_reg_lock); | ||
1573 | synch = inl(instance->preload_reg); | ||
1574 | synch &= | ||
1575 | ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance-> | ||
1576 | ao_idx); | ||
1577 | synch |= | ||
1578 | (instance->start_mode & ~ME4600_AO_EXT_TRIG) << instance->ao_idx; | ||
1579 | outl(synch, instance->preload_reg); | ||
1580 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1581 | instance->preload_reg - instance->reg_base, synch); | ||
1582 | spin_unlock(instance->preload_reg_lock); | ||
1583 | |||
1584 | //Default count is '0' | ||
1585 | if (instance->mode == ME4600_AO_CONTINOUS) { //Continous | ||
1586 | instance->preloaded_count = 0; | ||
1587 | instance->circ_buf.tail += count; | ||
1588 | instance->circ_buf.tail &= instance->circ_buf.mask; | ||
1589 | } else { //Wraparound | ||
1590 | instance->preloaded_count += count; | ||
1591 | instance->data_count += count; | ||
1592 | |||
1593 | //Special case: Infinite wraparound with less than FIFO datas always should runs in hardware mode. | ||
1594 | if ((instance->stop_mode == ME4600_AO_INF_STOP_MODE) | ||
1595 | && (circ_buffer_count <= ME4600_AO_FIFO_COUNT)) { //Change to hardware wraparound | ||
1596 | PDEBUG | ||
1597 | ("Changeing mode from software wraparound to hardware wraparound.\n"); | ||
1598 | //Copy all data | ||
1599 | count = | ||
1600 | ao_write_data(instance, circ_buffer_count, | ||
1601 | instance->preloaded_count); | ||
1602 | ctrl &= ~ME4600_AO_CTRL_MODE_MASK; | ||
1603 | ctrl |= ME4600_AO_MODE_WRAPAROUND; | ||
1604 | } | ||
1605 | |||
1606 | if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. | ||
1607 | instance->preloaded_count = 0; | ||
1608 | } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! | ||
1609 | PERROR_CRITICAL | ||
1610 | ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); | ||
1611 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
1612 | cpu_flags); | ||
1613 | ME_SUBDEVICE_EXIT; | ||
1614 | return ME_ERRNO_INTERNAL; | ||
1615 | } | ||
1616 | } | ||
1617 | |||
1618 | //Set status to 'wait for start' | ||
1619 | instance->status = ao_status_stream_run_wait; | ||
1620 | |||
1621 | status = inl(instance->status_reg); | ||
1622 | //Start state machine and interrupts | ||
1623 | ctrl &= ~(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
1624 | if (instance->start_mode == ME4600_AO_EXT_TRIG) { // External trigger. | ||
1625 | PINFO("External trigger.\n"); | ||
1626 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
1627 | } | ||
1628 | if (!(status & ME4600_AO_STATUS_BIT_HF)) { //More than half! | ||
1629 | 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 | ||
1630 | ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
1631 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
1632 | } | ||
1633 | } | ||
1634 | outl(ctrl, instance->ctrl_reg); | ||
1635 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1636 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1637 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
1638 | |||
1639 | //Trigger output | ||
1640 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs | ||
1641 | spin_lock(instance->preload_reg_lock); | ||
1642 | synch = inl(instance->preload_reg); | ||
1643 | //Add channel to start list | ||
1644 | outl(synch | (ME4600_AO_SYNC_HOLD << instance->ao_idx), | ||
1645 | instance->preload_reg); | ||
1646 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1647 | instance->reg_base, | ||
1648 | instance->preload_reg - instance->reg_base, | ||
1649 | synch | (ME4600_AO_SYNC_HOLD << instance->ao_idx)); | ||
1650 | |||
1651 | //Fire | ||
1652 | PINFO | ||
1653 | ("Fired all software synchronous outputs by software trigger.\n"); | ||
1654 | outl(0x8000, instance->single_reg); | ||
1655 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1656 | instance->reg_base, | ||
1657 | instance->single_reg - instance->reg_base, 0x8000); | ||
1658 | |||
1659 | //Restore save settings | ||
1660 | outl(synch, instance->preload_reg); | ||
1661 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1662 | instance->reg_base, | ||
1663 | instance->preload_reg - instance->reg_base, synch); | ||
1664 | spin_unlock(instance->preload_reg_lock); | ||
1665 | } else if (!instance->start_mode) { //Trigger outputs | ||
1666 | /* | ||
1667 | //Remove channel from start list. // <== Unnecessary. Removed. | ||
1668 | spin_lock(instance->preload_reg_lock); | ||
1669 | synch = inl(instance->preload_reg); | ||
1670 | outl(synch & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); | ||
1671 | 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)); | ||
1672 | */ | ||
1673 | //Fire | ||
1674 | PINFO("Software trigger.\n"); | ||
1675 | outl(0x8000, instance->single_reg); | ||
1676 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1677 | instance->reg_base, | ||
1678 | instance->single_reg - instance->reg_base, 0x8000); | ||
1679 | |||
1680 | /* | ||
1681 | //Restore save settings. // <== Unnecessary. Removed. | ||
1682 | outl(synch, instance->preload_reg); | ||
1683 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch); | ||
1684 | spin_unlock(instance->preload_reg_lock); | ||
1685 | */ | ||
1686 | } | ||
1687 | // Set control task's timeout | ||
1688 | ref = jiffies; | ||
1689 | instance->timeout.delay = delay; | ||
1690 | instance->timeout.start_time = ref; | ||
1691 | |||
1692 | if (status & ME4600_AO_STATUS_BIT_HF) { //Less than half but not empty! | ||
1693 | PINFO("Less than half.\n"); | ||
1694 | if (instance->stop_data_count != 0) { | ||
1695 | count = ME4600_AO_FIFO_COUNT / 2; | ||
1696 | } else { | ||
1697 | count = | ||
1698 | ((ME4600_AO_FIFO_COUNT / 2) < | ||
1699 | instance->stop_data_count) ? ME4600_AO_FIFO_COUNT / | ||
1700 | 2 : instance->stop_data_count; | ||
1701 | } | ||
1702 | |||
1703 | //Copy data | ||
1704 | count = | ||
1705 | ao_write_data(instance, count, instance->preloaded_count); | ||
1706 | |||
1707 | if (count < 0) { //This should never happend! | ||
1708 | PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); | ||
1709 | ME_SUBDEVICE_EXIT; | ||
1710 | return ME_ERRNO_INTERNAL; | ||
1711 | } | ||
1712 | |||
1713 | if (instance->mode == ME4600_AO_CONTINOUS) { //Continous | ||
1714 | instance->circ_buf.tail += count; | ||
1715 | instance->circ_buf.tail &= instance->circ_buf.mask; | ||
1716 | } else { //Wraparound | ||
1717 | instance->data_count += count; | ||
1718 | instance->preloaded_count += count; | ||
1719 | |||
1720 | if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. | ||
1721 | instance->preloaded_count = 0; | ||
1722 | } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! | ||
1723 | PERROR_CRITICAL | ||
1724 | ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); | ||
1725 | ME_SUBDEVICE_EXIT; | ||
1726 | return ME_ERRNO_INTERNAL; | ||
1727 | } | ||
1728 | } | ||
1729 | |||
1730 | status = inl(instance->status_reg); | ||
1731 | if (!(status & ME4600_AO_STATUS_BIT_HF)) { //More than half! | ||
1732 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1733 | ctrl = inl(instance->ctrl_reg); | ||
1734 | ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
1735 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
1736 | outl(ctrl, instance->ctrl_reg); | ||
1737 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1738 | instance->reg_base, | ||
1739 | instance->ctrl_reg - instance->reg_base, | ||
1740 | ctrl); | ||
1741 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
1742 | cpu_flags); | ||
1743 | } | ||
1744 | } | ||
1745 | //Special case: Limited wraparound with less than HALF FIFO datas need work around to generate first interrupt. | ||
1746 | if ((instance->stop_mode != ME4600_AO_INF_STOP_MODE) | ||
1747 | && (instance->mode == ME4600_AO_SW_WRAP_MODE) | ||
1748 | && (circ_buffer_count <= (ME4600_AO_FIFO_COUNT / 2))) { //Put more data to FIFO | ||
1749 | PINFO("Limited wraparound with less than HALF FIFO datas.\n"); | ||
1750 | if (instance->preloaded_count) { //This should never happend! | ||
1751 | PERROR_CRITICAL | ||
1752 | ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); | ||
1753 | ME_SUBDEVICE_EXIT; | ||
1754 | return ME_ERRNO_INTERNAL; | ||
1755 | } | ||
1756 | |||
1757 | while (instance->stop_data_count > instance->data_count) { //Maximum data not set jet. | ||
1758 | //Copy to buffer | ||
1759 | if (circ_buffer_count != ao_write_data(instance, circ_buffer_count, 0)) { //This should never happend! | ||
1760 | PERROR_CRITICAL | ||
1761 | ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); | ||
1762 | ME_SUBDEVICE_EXIT; | ||
1763 | return ME_ERRNO_INTERNAL; | ||
1764 | } | ||
1765 | instance->data_count += circ_buffer_count; | ||
1766 | |||
1767 | if (!((status = inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_HF)) { //FIFO is more than half. Enable IRQ and end copy. | ||
1768 | spin_lock_irqsave(&instance->subdevice_lock, | ||
1769 | cpu_flags); | ||
1770 | ctrl = inl(instance->ctrl_reg); | ||
1771 | ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
1772 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
1773 | outl(ctrl, instance->ctrl_reg); | ||
1774 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1775 | instance->reg_base, | ||
1776 | instance->ctrl_reg - | ||
1777 | instance->reg_base, ctrl); | ||
1778 | spin_unlock_irqrestore(&instance-> | ||
1779 | subdevice_lock, | ||
1780 | cpu_flags); | ||
1781 | break; | ||
1782 | } | ||
1783 | } | ||
1784 | } | ||
1785 | // Schedule control task. | ||
1786 | instance->ao_control_task_flag = 1; | ||
1787 | queue_delayed_work(instance->me4600_workqueue, | ||
1788 | &instance->ao_control_task, 1); | ||
1789 | |||
1790 | if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start. | ||
1791 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
1792 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1793 | (instance->status != | ||
1794 | ao_status_stream_run_wait), | ||
1795 | (delay) ? delay + | ||
1796 | 1 : LONG_MAX); | ||
1797 | |||
1798 | if ((instance->status != ao_status_stream_run) | ||
1799 | && (instance->status != ao_status_stream_end)) { | ||
1800 | PDEBUG("Starting stream canceled. %d\n", | ||
1801 | instance->status); | ||
1802 | err = ME_ERRNO_CANCELLED; | ||
1803 | } | ||
1804 | |||
1805 | if (signal_pending(current)) { | ||
1806 | PERROR("Wait on start of state machine interrupted.\n"); | ||
1807 | instance->status = ao_status_none; | ||
1808 | ao_stop_immediately(instance); | ||
1809 | err = ME_ERRNO_SIGNAL; | ||
1810 | } else if ((delay) && ((jiffies - ref) >= delay)) { | ||
1811 | if (instance->status != ao_status_stream_run) { | ||
1812 | if (instance->status == ao_status_stream_end) { | ||
1813 | PDEBUG("Timeout reached.\n"); | ||
1814 | } else { | ||
1815 | if ((jiffies - ref) > delay) { | ||
1816 | PERROR | ||
1817 | ("Timeout reached. Not handled by control task!\n"); | ||
1818 | } else { | ||
1819 | PERROR | ||
1820 | ("Timeout reached. Signal come but status is strange: %d\n", | ||
1821 | instance->status); | ||
1822 | } | ||
1823 | ao_stop_immediately(instance); | ||
1824 | } | ||
1825 | |||
1826 | instance->ao_control_task_flag = 0; | ||
1827 | cancel_delayed_work(&instance->ao_control_task); | ||
1828 | instance->status = ao_status_stream_end; | ||
1829 | err = ME_ERRNO_TIMEOUT; | ||
1830 | } | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1834 | ME_SUBDEVICE_EXIT; | ||
1835 | return err; | ||
1836 | } | ||
1837 | |||
1838 | static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, | ||
1839 | struct file *filep, | ||
1840 | int wait, | ||
1841 | int *status, int *values, int flags) | ||
1842 | { | ||
1843 | me4600_ao_subdevice_t *instance; | ||
1844 | int err = ME_ERRNO_SUCCESS; | ||
1845 | |||
1846 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
1847 | |||
1848 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1849 | |||
1850 | if (!instance->fifo) { | ||
1851 | PERROR("Not a streaming ao.\n"); | ||
1852 | return ME_ERRNO_NOT_SUPPORTED; | ||
1853 | } | ||
1854 | |||
1855 | if (flags) { | ||
1856 | PERROR("Invalid flag specified.\n"); | ||
1857 | return ME_ERRNO_INVALID_FLAGS; | ||
1858 | } | ||
1859 | |||
1860 | if ((wait != ME_WAIT_NONE) && (wait != ME_WAIT_IDLE)) { | ||
1861 | PERROR("Invalid wait argument specified.\n"); | ||
1862 | *status = ME_STATUS_INVALID; | ||
1863 | return ME_ERRNO_INVALID_WAIT; | ||
1864 | } | ||
1865 | |||
1866 | ME_SUBDEVICE_ENTER; | ||
1867 | |||
1868 | switch (instance->status) { | ||
1869 | case ao_status_single_configured: | ||
1870 | case ao_status_single_end: | ||
1871 | case ao_status_stream_configured: | ||
1872 | case ao_status_stream_end: | ||
1873 | case ao_status_stream_fifo_error: | ||
1874 | case ao_status_stream_buffer_error: | ||
1875 | case ao_status_stream_error: | ||
1876 | *status = ME_STATUS_IDLE; | ||
1877 | break; | ||
1878 | |||
1879 | case ao_status_single_run_wait: | ||
1880 | case ao_status_single_run: | ||
1881 | case ao_status_single_end_wait: | ||
1882 | case ao_status_stream_run_wait: | ||
1883 | case ao_status_stream_run: | ||
1884 | case ao_status_stream_end_wait: | ||
1885 | *status = ME_STATUS_BUSY; | ||
1886 | break; | ||
1887 | |||
1888 | case ao_status_none: | ||
1889 | default: | ||
1890 | *status = | ||
1891 | (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ? | ||
1892 | ME_STATUS_BUSY : ME_STATUS_IDLE; | ||
1893 | break; | ||
1894 | } | ||
1895 | |||
1896 | if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) { | ||
1897 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
1898 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1899 | ((instance->status != | ||
1900 | ao_status_single_run_wait) | ||
1901 | && (instance->status != | ||
1902 | ao_status_single_run) | ||
1903 | && (instance->status != | ||
1904 | ao_status_single_end_wait) | ||
1905 | && (instance->status != | ||
1906 | ao_status_stream_run_wait) | ||
1907 | && (instance->status != | ||
1908 | ao_status_stream_run) | ||
1909 | && (instance->status != | ||
1910 | ao_status_stream_end_wait)), | ||
1911 | LONG_MAX); | ||
1912 | |||
1913 | if (instance->status != ao_status_stream_end) { | ||
1914 | PDEBUG("Wait for IDLE canceled. %d\n", | ||
1915 | instance->status); | ||
1916 | err = ME_ERRNO_CANCELLED; | ||
1917 | } | ||
1918 | |||
1919 | if (signal_pending(current)) { | ||
1920 | PERROR("Wait for IDLE interrupted.\n"); | ||
1921 | instance->status = ao_status_none; | ||
1922 | ao_stop_immediately(instance); | ||
1923 | err = ME_ERRNO_SIGNAL; | ||
1924 | } | ||
1925 | |||
1926 | *status = ME_STATUS_IDLE; | ||
1927 | } | ||
1928 | |||
1929 | *values = me_circ_buf_space(&instance->circ_buf); | ||
1930 | |||
1931 | ME_SUBDEVICE_EXIT; | ||
1932 | |||
1933 | return err; | ||
1934 | } | ||
1935 | |||
1936 | static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, | ||
1937 | struct file *filep, | ||
1938 | int stop_mode, int flags) | ||
1939 | { // Stop work and empty buffer and FIFO | ||
1940 | int err = ME_ERRNO_SUCCESS; | ||
1941 | me4600_ao_subdevice_t *instance; | ||
1942 | unsigned long cpu_flags; | ||
1943 | volatile uint32_t ctrl; | ||
1944 | |||
1945 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
1946 | |||
1947 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1948 | |||
1949 | if (flags & ~ME_IO_STREAM_STOP_PRESERVE_BUFFERS) { | ||
1950 | PERROR("Invalid flag specified.\n"); | ||
1951 | return ME_ERRNO_INVALID_FLAGS; | ||
1952 | } | ||
1953 | |||
1954 | if ((stop_mode != ME_STOP_MODE_IMMEDIATE) | ||
1955 | && (stop_mode != ME_STOP_MODE_LAST_VALUE)) { | ||
1956 | PERROR("Invalid stop mode specified.\n"); | ||
1957 | return ME_ERRNO_INVALID_STOP_MODE; | ||
1958 | } | ||
1959 | |||
1960 | if (!instance->fifo) { | ||
1961 | PERROR("Not a streaming ao.\n"); | ||
1962 | return ME_ERRNO_NOT_SUPPORTED; | ||
1963 | } | ||
1964 | |||
1965 | if (instance->status < ao_status_stream_configured) { | ||
1966 | //There is nothing to stop! | ||
1967 | PERROR("Subdevice not in streaming mode. %d\n", | ||
1968 | instance->status); | ||
1969 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
1970 | } | ||
1971 | |||
1972 | ME_SUBDEVICE_ENTER; | ||
1973 | |||
1974 | //Mark as stopping. => Software stop. | ||
1975 | instance->status = ao_status_stream_end_wait; | ||
1976 | |||
1977 | if (stop_mode == ME_STOP_MODE_IMMEDIATE) { //Stopped now! | ||
1978 | err = ao_stop_immediately(instance); | ||
1979 | } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { | ||
1980 | ctrl = inl(instance->ctrl_reg) & ME4600_AO_CTRL_MODE_MASK; | ||
1981 | if (ctrl == ME4600_AO_MODE_WRAPAROUND) { //Hardware wraparound => Hardware stop. | ||
1982 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1983 | ctrl = inl(instance->ctrl_reg); | ||
1984 | ctrl |= | ||
1985 | ME4600_AO_CTRL_BIT_STOP | | ||
1986 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
1987 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
1988 | outl(ctrl, instance->ctrl_reg); | ||
1989 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1990 | instance->reg_base, | ||
1991 | instance->ctrl_reg - instance->reg_base, | ||
1992 | ctrl); | ||
1993 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
1994 | cpu_flags); | ||
1995 | } | ||
1996 | //Only runing process will interrupt this call. Events are signaled when status change. | ||
1997 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1998 | (instance->status != | ||
1999 | ao_status_stream_end_wait), | ||
2000 | LONG_MAX); | ||
2001 | |||
2002 | if (instance->status != ao_status_stream_end) { | ||
2003 | PDEBUG("Stopping stream canceled.\n"); | ||
2004 | err = ME_ERRNO_CANCELLED; | ||
2005 | } | ||
2006 | |||
2007 | if (signal_pending(current)) { | ||
2008 | PERROR("Stopping stream interrupted.\n"); | ||
2009 | instance->status = ao_status_none; | ||
2010 | ao_stop_immediately(instance); | ||
2011 | err = ME_ERRNO_SIGNAL; | ||
2012 | } | ||
2013 | } | ||
2014 | |||
2015 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2016 | ctrl = inl(instance->ctrl_reg); | ||
2017 | ctrl |= | ||
2018 | ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | | ||
2019 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2020 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2021 | if (!flags) { //Reset FIFO | ||
2022 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO; | ||
2023 | } | ||
2024 | outl(ctrl, instance->ctrl_reg); | ||
2025 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
2026 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2027 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
2028 | |||
2029 | if (!flags) { //Reset software buffer | ||
2030 | instance->circ_buf.head = 0; | ||
2031 | instance->circ_buf.tail = 0; | ||
2032 | instance->preloaded_count = 0; | ||
2033 | instance->data_count = 0; | ||
2034 | } | ||
2035 | |||
2036 | ME_SUBDEVICE_EXIT; | ||
2037 | |||
2038 | return err; | ||
2039 | } | ||
2040 | |||
2041 | static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, | ||
2042 | struct file *filep, | ||
2043 | int write_mode, | ||
2044 | int *values, int *count, int flags) | ||
2045 | { | ||
2046 | int err = ME_ERRNO_SUCCESS; | ||
2047 | me4600_ao_subdevice_t *instance; | ||
2048 | unsigned long cpu_flags = 0; | ||
2049 | uint32_t reg_copy; | ||
2050 | |||
2051 | int copied_from_user = 0; | ||
2052 | int left_to_copy_from_user = *count; | ||
2053 | |||
2054 | int copied_values; | ||
2055 | |||
2056 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
2057 | |||
2058 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
2059 | |||
2060 | //Checking arguments | ||
2061 | if (!instance->fifo) { | ||
2062 | PERROR("Not a streaming ao.\n"); | ||
2063 | return ME_ERRNO_NOT_SUPPORTED; | ||
2064 | } | ||
2065 | |||
2066 | if (flags) { | ||
2067 | PERROR("Invalid flag specified.\n"); | ||
2068 | return ME_ERRNO_INVALID_FLAGS; | ||
2069 | } | ||
2070 | |||
2071 | if (*count <= 0) { | ||
2072 | PERROR("Invalid count of values specified.\n"); | ||
2073 | return ME_ERRNO_INVALID_VALUE_COUNT; | ||
2074 | } | ||
2075 | |||
2076 | if (values == NULL) { | ||
2077 | PERROR("Invalid address of values specified.\n"); | ||
2078 | return ME_ERRNO_INVALID_POINTER; | ||
2079 | } | ||
2080 | |||
2081 | if ((instance->status == ao_status_none) || (instance->status == ao_status_single_configured)) { //The device is in single mode. | ||
2082 | PERROR | ||
2083 | ("Subdevice must be preinitialize correctly for streaming.\n"); | ||
2084 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
2085 | } | ||
2086 | /// @note If no 'pre-load' is used. stream_start() will move data to FIFO. | ||
2087 | switch (write_mode) { | ||
2088 | case ME_WRITE_MODE_PRELOAD: | ||
2089 | |||
2090 | //Device must be stopped. | ||
2091 | if ((instance->status != ao_status_stream_configured) | ||
2092 | && (instance->status != ao_status_stream_end)) { | ||
2093 | PERROR | ||
2094 | ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); | ||
2095 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
2096 | } | ||
2097 | break; | ||
2098 | case ME_WRITE_MODE_NONBLOCKING: | ||
2099 | case ME_WRITE_MODE_BLOCKING: | ||
2100 | /// @note In blocking mode: When device is not runing and there is not enought space call will blocked up! | ||
2101 | /// @note Some other thread must empty buffer by starting engine. | ||
2102 | break; | ||
2103 | |||
2104 | default: | ||
2105 | PERROR("Invalid write mode specified.\n"); | ||
2106 | return ME_ERRNO_INVALID_WRITE_MODE; | ||
2107 | } | ||
2108 | |||
2109 | if (instance->mode & ME4600_AO_WRAP_MODE) { //Wraparound mode. Device must be stopped. | ||
2110 | if ((instance->status != ao_status_stream_configured) | ||
2111 | && (instance->status != ao_status_stream_end)) { | ||
2112 | PERROR | ||
2113 | ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); | ||
2114 | return ME_ERRNO_INVALID_WRITE_MODE; | ||
2115 | } | ||
2116 | } | ||
2117 | |||
2118 | if ((instance->mode == ME4600_AO_HW_WRAP_MODE) && (write_mode != ME_WRITE_MODE_PRELOAD)) { // hardware wrap_around mode. | ||
2119 | //This is transparent for user. | ||
2120 | PDEBUG("Changing write_mode to ME_WRITE_MODE_PRELOAD.\n"); | ||
2121 | write_mode = ME_WRITE_MODE_PRELOAD; | ||
2122 | } | ||
2123 | |||
2124 | ME_SUBDEVICE_ENTER; | ||
2125 | |||
2126 | if (write_mode == ME_WRITE_MODE_PRELOAD) { //Init enviroment - preload | ||
2127 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2128 | reg_copy = inl(instance->ctrl_reg); | ||
2129 | //Check FIFO | ||
2130 | if (!(reg_copy & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO not active. Enable it. | ||
2131 | reg_copy |= ME4600_AO_CTRL_BIT_ENABLE_FIFO; | ||
2132 | outl(reg_copy, instance->ctrl_reg); | ||
2133 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2134 | instance->reg_base, | ||
2135 | instance->ctrl_reg - instance->reg_base, | ||
2136 | reg_copy); | ||
2137 | instance->preloaded_count = 0; | ||
2138 | } | ||
2139 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
2140 | } | ||
2141 | |||
2142 | while (1) { | ||
2143 | //Copy to buffer. This step is common for all modes. | ||
2144 | copied_from_user = | ||
2145 | ao_get_data_from_user(instance, left_to_copy_from_user, | ||
2146 | values + (*count - | ||
2147 | left_to_copy_from_user)); | ||
2148 | left_to_copy_from_user -= copied_from_user; | ||
2149 | |||
2150 | reg_copy = inl(instance->status_reg); | ||
2151 | 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. | ||
2152 | PERROR("Broken pipe in write.\n"); | ||
2153 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
2154 | break; | ||
2155 | } | ||
2156 | |||
2157 | 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! | ||
2158 | |||
2159 | // Block interrupts. | ||
2160 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2161 | reg_copy = inl(instance->ctrl_reg); | ||
2162 | //reg_copy &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2163 | reg_copy |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2164 | outl(reg_copy, instance->ctrl_reg); | ||
2165 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2166 | instance->reg_base, | ||
2167 | instance->ctrl_reg - instance->reg_base, | ||
2168 | reg_copy); | ||
2169 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
2170 | cpu_flags); | ||
2171 | |||
2172 | //Fast copy | ||
2173 | copied_values = | ||
2174 | ao_write_data(instance, ME4600_AO_FIFO_COUNT / 2, | ||
2175 | 0); | ||
2176 | if (copied_values > 0) { | ||
2177 | instance->circ_buf.tail += copied_values; | ||
2178 | instance->circ_buf.tail &= | ||
2179 | instance->circ_buf.mask; | ||
2180 | continue; | ||
2181 | } | ||
2182 | // Activate interrupts. | ||
2183 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2184 | reg_copy = inl(instance->ctrl_reg); | ||
2185 | //reg_copy |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2186 | reg_copy &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2187 | outl(reg_copy, instance->ctrl_reg); | ||
2188 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2189 | instance->reg_base, | ||
2190 | instance->ctrl_reg - instance->reg_base, | ||
2191 | reg_copy); | ||
2192 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
2193 | cpu_flags); | ||
2194 | |||
2195 | if (copied_values == 0) { //This was checked and never should happend! | ||
2196 | PERROR_CRITICAL("COPING FINISH WITH 0!\n"); | ||
2197 | } | ||
2198 | |||
2199 | if (copied_values < 0) { //This was checked and never should happend! | ||
2200 | PERROR_CRITICAL | ||
2201 | ("COPING FINISH WITH AN ERROR!\n"); | ||
2202 | instance->status = ao_status_stream_fifo_error; | ||
2203 | err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2204 | break; | ||
2205 | } | ||
2206 | } | ||
2207 | |||
2208 | if (!left_to_copy_from_user) { //All datas were copied. | ||
2209 | break; | ||
2210 | } else { //Not all datas were copied. | ||
2211 | if (instance->mode & ME4600_AO_WRAP_MODE) { //Error too much datas! Wraparound is limited in size! | ||
2212 | PERROR | ||
2213 | ("Too much data for wraparound mode! Exceeded size of %ld.\n", | ||
2214 | ME4600_AO_CIRC_BUF_COUNT - 1); | ||
2215 | err = ME_ERRNO_RING_BUFFER_OVERFLOW; | ||
2216 | break; | ||
2217 | } | ||
2218 | |||
2219 | if (write_mode != ME_WRITE_MODE_BLOCKING) { //Non blocking calls | ||
2220 | break; | ||
2221 | } | ||
2222 | |||
2223 | wait_event_interruptible(instance->wait_queue, | ||
2224 | me_circ_buf_space(&instance-> | ||
2225 | circ_buf)); | ||
2226 | |||
2227 | if (signal_pending(current)) { | ||
2228 | PERROR("Writing interrupted by signal.\n"); | ||
2229 | instance->status = ao_status_none; | ||
2230 | ao_stop_immediately(instance); | ||
2231 | err = ME_ERRNO_SIGNAL; | ||
2232 | break; | ||
2233 | } | ||
2234 | |||
2235 | if (instance->status == ao_status_none) { //Reset | ||
2236 | PERROR("Writing interrupted by reset.\n"); | ||
2237 | err = ME_ERRNO_CANCELLED; | ||
2238 | break; | ||
2239 | } | ||
2240 | } | ||
2241 | } | ||
2242 | |||
2243 | if (write_mode == ME_WRITE_MODE_PRELOAD) { //Copy data to FIFO - preload | ||
2244 | copied_values = | ||
2245 | ao_write_data_pooling(instance, ME4600_AO_FIFO_COUNT, | ||
2246 | instance->preloaded_count); | ||
2247 | instance->preloaded_count += copied_values; | ||
2248 | instance->data_count += copied_values; | ||
2249 | |||
2250 | if ((instance->mode == ME4600_AO_HW_WRAP_MODE) | ||
2251 | && (me_circ_buf_values(&instance->circ_buf) > | ||
2252 | ME4600_AO_FIFO_COUNT)) { | ||
2253 | PERROR | ||
2254 | ("Too much data for hardware wraparound mode! Exceeded size of %d.\n", | ||
2255 | ME4600_AO_FIFO_COUNT); | ||
2256 | err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2257 | } | ||
2258 | } | ||
2259 | |||
2260 | *count = *count - left_to_copy_from_user; | ||
2261 | ME_SUBDEVICE_EXIT; | ||
2262 | |||
2263 | return err; | ||
2264 | } | ||
2265 | static irqreturn_t me4600_ao_isr(int irq, void *dev_id) | ||
2266 | { | ||
2267 | me4600_ao_subdevice_t *instance = dev_id; | ||
2268 | uint32_t irq_status; | ||
2269 | uint32_t ctrl; | ||
2270 | uint32_t status; | ||
2271 | int count = 0; | ||
2272 | |||
2273 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
2274 | |||
2275 | if (irq != instance->irq) { | ||
2276 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
2277 | return IRQ_NONE; | ||
2278 | } | ||
2279 | |||
2280 | irq_status = inl(instance->irq_status_reg); | ||
2281 | if (!(irq_status & (ME4600_IRQ_STATUS_BIT_AO_HF << instance->ao_idx))) { | ||
2282 | PINFO("%ld Shared interrupt. %s(): ID=%d: status_reg=0x%04X\n", | ||
2283 | jiffies, __func__, instance->ao_idx, irq_status); | ||
2284 | return IRQ_NONE; | ||
2285 | } | ||
2286 | |||
2287 | if (!instance->circ_buf.buf) { | ||
2288 | instance->status = ao_status_stream_error; | ||
2289 | PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n"); | ||
2290 | //Block interrupts. Stop machine. | ||
2291 | ctrl = inl(instance->ctrl_reg); | ||
2292 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2293 | ctrl |= | ||
2294 | ME4600_AO_CTRL_BIT_RESET_IRQ | | ||
2295 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP; | ||
2296 | outl(ctrl, instance->ctrl_reg); | ||
2297 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2298 | instance->reg_base, | ||
2299 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2300 | |||
2301 | //Inform user | ||
2302 | wake_up_interruptible_all(&instance->wait_queue); | ||
2303 | return IRQ_HANDLED; | ||
2304 | } | ||
2305 | |||
2306 | status = inl(instance->status_reg); | ||
2307 | if (!(status & ME4600_AO_STATUS_BIT_FSM)) { //Too late. Not working! END? BROKEN PIPE? | ||
2308 | PDEBUG("Interrupt come but ISM is not working!\n"); | ||
2309 | //Block interrupts. Stop machine. | ||
2310 | ctrl = inl(instance->ctrl_reg); | ||
2311 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2312 | ctrl |= | ||
2313 | ME4600_AO_CTRL_BIT_RESET_IRQ | ME4600_AO_CTRL_BIT_STOP | | ||
2314 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
2315 | outl(ctrl, instance->ctrl_reg); | ||
2316 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2317 | instance->reg_base, | ||
2318 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2319 | |||
2320 | return IRQ_HANDLED; | ||
2321 | } | ||
2322 | //General procedure. Process more datas. | ||
2323 | |||
2324 | #ifdef MEDEBUG_DEBUG | ||
2325 | if (!me_circ_buf_values(&instance->circ_buf)) { //Buffer is empty! | ||
2326 | PDEBUG("Circular buffer empty!\n"); | ||
2327 | } | ||
2328 | #endif | ||
2329 | |||
2330 | //Check FIFO | ||
2331 | if (status & ME4600_AO_STATUS_BIT_HF) { //OK less than half | ||
2332 | |||
2333 | //Block interrupts | ||
2334 | ctrl = inl(instance->ctrl_reg); | ||
2335 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2336 | ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2337 | outl(ctrl, instance->ctrl_reg); | ||
2338 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2339 | instance->reg_base, | ||
2340 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2341 | |||
2342 | do { | ||
2343 | //Calculate how many should be copied. | ||
2344 | count = | ||
2345 | (instance->stop_data_count) ? instance-> | ||
2346 | stop_data_count - | ||
2347 | instance->data_count : ME4600_AO_FIFO_COUNT / 2; | ||
2348 | if (ME4600_AO_FIFO_COUNT / 2 < count) { | ||
2349 | count = ME4600_AO_FIFO_COUNT / 2; | ||
2350 | } | ||
2351 | //Copy data | ||
2352 | if (instance->mode == ME4600_AO_CONTINOUS) { //Continous | ||
2353 | count = ao_write_data(instance, count, 0); | ||
2354 | if (count > 0) { | ||
2355 | instance->circ_buf.tail += count; | ||
2356 | instance->circ_buf.tail &= | ||
2357 | instance->circ_buf.mask; | ||
2358 | instance->data_count += count; | ||
2359 | |||
2360 | if ((instance->status == ao_status_stream_end_wait) && !me_circ_buf_values(&instance->circ_buf)) { //Stoping. Whole buffer was copied. | ||
2361 | break; | ||
2362 | } | ||
2363 | } | ||
2364 | } else if ((instance->mode == ME4600_AO_SW_WRAP_MODE) && ((ctrl & ME4600_AO_CTRL_MODE_MASK) == ME4600_AO_MODE_CONTINUOUS)) { //Wraparound (software) | ||
2365 | if (instance->status == ao_status_stream_end_wait) { //We stoping => Copy to the end of the buffer. | ||
2366 | count = | ||
2367 | ao_write_data(instance, count, 0); | ||
2368 | } else { //Copy in wraparound mode. | ||
2369 | count = | ||
2370 | ao_write_data_wraparound(instance, | ||
2371 | count, | ||
2372 | instance-> | ||
2373 | preloaded_count); | ||
2374 | } | ||
2375 | |||
2376 | if (count > 0) { | ||
2377 | instance->data_count += count; | ||
2378 | instance->preloaded_count += count; | ||
2379 | instance->preloaded_count %= | ||
2380 | me_circ_buf_values(&instance-> | ||
2381 | circ_buf); | ||
2382 | |||
2383 | if ((instance->status == ao_status_stream_end_wait) && !instance->preloaded_count) { //Stoping. Whole buffer was copied. | ||
2384 | break; | ||
2385 | } | ||
2386 | } | ||
2387 | } | ||
2388 | |||
2389 | if ((count <= 0) || (instance->stop_data_count && (instance->stop_data_count <= instance->data_count))) { //End of work. | ||
2390 | break; | ||
2391 | } | ||
2392 | } //Repeat if still is under half fifo | ||
2393 | while ((status = | ||
2394 | inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_HF); | ||
2395 | |||
2396 | //Unblock interrupts | ||
2397 | ctrl = inl(instance->ctrl_reg); | ||
2398 | if (count >= 0) { //Copy was successful. | ||
2399 | if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. No more interrupts. | ||
2400 | PDEBUG("Finishing work. Interrupt disabled.\n"); | ||
2401 | instance->status = ao_status_stream_end_wait; | ||
2402 | } else if (count > 0) { //Normal work. Enable interrupt. | ||
2403 | PDEBUG("Normal work. Enable interrupt.\n"); | ||
2404 | ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2405 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2406 | } else { //Normal work but there are no more data in buffer. Interrupt active but blocked. stream_write() will unblock it. | ||
2407 | PDEBUG | ||
2408 | ("No data in software buffer. Interrupt blocked.\n"); | ||
2409 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
2410 | } | ||
2411 | } else { //Error during copy. | ||
2412 | instance->status = ao_status_stream_fifo_error; | ||
2413 | } | ||
2414 | |||
2415 | outl(ctrl, instance->ctrl_reg); | ||
2416 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2417 | instance->reg_base, | ||
2418 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2419 | } else { //?? more than half | ||
2420 | PDEBUG | ||
2421 | ("Interrupt come but FIFO more than half full! Reset interrupt.\n"); | ||
2422 | //Reset pending interrupt | ||
2423 | ctrl = inl(instance->ctrl_reg); | ||
2424 | ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2425 | outl(ctrl, instance->ctrl_reg); | ||
2426 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2427 | instance->reg_base, | ||
2428 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2429 | ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2430 | outl(ctrl, instance->ctrl_reg); | ||
2431 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2432 | instance->reg_base, | ||
2433 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2434 | } | ||
2435 | |||
2436 | PINFO("ISR: Buffer count: %d.(T:%d H:%d)\n", | ||
2437 | me_circ_buf_values(&instance->circ_buf), instance->circ_buf.tail, | ||
2438 | instance->circ_buf.head); | ||
2439 | PINFO("ISR: Stop count: %d.\n", instance->stop_count); | ||
2440 | PINFO("ISR: Stop data count: %d.\n", instance->stop_data_count); | ||
2441 | PINFO("ISR: Data count: %d.\n", instance->data_count); | ||
2442 | |||
2443 | //Inform user | ||
2444 | wake_up_interruptible_all(&instance->wait_queue); | ||
2445 | |||
2446 | return IRQ_HANDLED; | ||
2447 | } | ||
2448 | |||
2449 | static void me4600_ao_destructor(struct me_subdevice *subdevice) | ||
2450 | { | ||
2451 | me4600_ao_subdevice_t *instance; | ||
2452 | |||
2453 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
2454 | |||
2455 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
2456 | |||
2457 | instance->ao_control_task_flag = 0; | ||
2458 | |||
2459 | // Reset subdevice to asure clean exit. | ||
2460 | me4600_ao_io_reset_subdevice(subdevice, NULL, | ||
2461 | ME_IO_RESET_SUBDEVICE_NO_FLAGS); | ||
2462 | |||
2463 | // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). | ||
2464 | if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. | ||
2465 | set_current_state(TASK_INTERRUPTIBLE); | ||
2466 | schedule_timeout(2); | ||
2467 | } | ||
2468 | |||
2469 | if (instance->fifo) { | ||
2470 | if (instance->irq) { | ||
2471 | free_irq(instance->irq, instance); | ||
2472 | instance->irq = 0; | ||
2473 | } | ||
2474 | |||
2475 | if (instance->circ_buf.buf) { | ||
2476 | free_pages((unsigned long)instance->circ_buf.buf, | ||
2477 | ME4600_AO_CIRC_BUF_SIZE_ORDER); | ||
2478 | } | ||
2479 | instance->circ_buf.buf = NULL; | ||
2480 | } | ||
2481 | |||
2482 | me_subdevice_deinit(&instance->base); | ||
2483 | kfree(instance); | ||
2484 | } | ||
2485 | |||
2486 | me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, | ||
2487 | spinlock_t *preload_reg_lock, | ||
2488 | uint32_t *preload_flags, | ||
2489 | int ao_idx, | ||
2490 | int fifo, | ||
2491 | int irq, | ||
2492 | struct workqueue_struct *me4600_wq) | ||
2493 | { | ||
2494 | me4600_ao_subdevice_t *subdevice; | ||
2495 | int err; | ||
2496 | |||
2497 | PDEBUG("executed. idx=%d\n", ao_idx); | ||
2498 | |||
2499 | // Allocate memory for subdevice instance. | ||
2500 | subdevice = kmalloc(sizeof(me4600_ao_subdevice_t), GFP_KERNEL); | ||
2501 | |||
2502 | if (!subdevice) { | ||
2503 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
2504 | return NULL; | ||
2505 | } | ||
2506 | |||
2507 | memset(subdevice, 0, sizeof(me4600_ao_subdevice_t)); | ||
2508 | |||
2509 | // Initialize subdevice base class. | ||
2510 | err = me_subdevice_init(&subdevice->base); | ||
2511 | |||
2512 | if (err) { | ||
2513 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
2514 | kfree(subdevice); | ||
2515 | return NULL; | ||
2516 | } | ||
2517 | // Initialize spin locks. | ||
2518 | spin_lock_init(&subdevice->subdevice_lock); | ||
2519 | |||
2520 | subdevice->preload_reg_lock = preload_reg_lock; | ||
2521 | subdevice->preload_flags = preload_flags; | ||
2522 | |||
2523 | // Store analog output index. | ||
2524 | subdevice->ao_idx = ao_idx; | ||
2525 | |||
2526 | // Store if analog output has fifo. | ||
2527 | subdevice->fifo = (ao_idx < fifo) ? 1 : 0; | ||
2528 | |||
2529 | if (subdevice->fifo) { // Allocate and initialize circular buffer. | ||
2530 | subdevice->circ_buf.mask = ME4600_AO_CIRC_BUF_COUNT - 1; | ||
2531 | |||
2532 | subdevice->circ_buf.buf = | ||
2533 | (void *)__get_free_pages(GFP_KERNEL, | ||
2534 | ME4600_AO_CIRC_BUF_SIZE_ORDER); | ||
2535 | PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf, | ||
2536 | ME4600_AO_CIRC_BUF_SIZE); | ||
2537 | |||
2538 | if (!subdevice->circ_buf.buf) { | ||
2539 | PERROR | ||
2540 | ("Cannot initialize subdevice base class instance.\n"); | ||
2541 | kfree(subdevice); | ||
2542 | return NULL; | ||
2543 | } | ||
2544 | |||
2545 | memset(subdevice->circ_buf.buf, 0, ME4600_AO_CIRC_BUF_SIZE); | ||
2546 | } else { // No FIFO. | ||
2547 | subdevice->circ_buf.mask = 0; | ||
2548 | subdevice->circ_buf.buf = NULL; | ||
2549 | } | ||
2550 | |||
2551 | subdevice->circ_buf.head = 0; | ||
2552 | subdevice->circ_buf.tail = 0; | ||
2553 | |||
2554 | subdevice->status = ao_status_none; | ||
2555 | subdevice->ao_control_task_flag = 0; | ||
2556 | subdevice->timeout.delay = 0; | ||
2557 | subdevice->timeout.start_time = jiffies; | ||
2558 | |||
2559 | // Initialize wait queue. | ||
2560 | init_waitqueue_head(&subdevice->wait_queue); | ||
2561 | |||
2562 | // Initialize single value to 0V. | ||
2563 | subdevice->single_value = 0x8000; | ||
2564 | subdevice->single_value_in_fifo = 0x8000; | ||
2565 | |||
2566 | // Register interrupt service routine. | ||
2567 | if (subdevice->fifo) { | ||
2568 | subdevice->irq = irq; | ||
2569 | if (request_irq(subdevice->irq, me4600_ao_isr, | ||
2570 | IRQF_DISABLED | IRQF_SHARED, | ||
2571 | ME4600_NAME, subdevice)) { | ||
2572 | PERROR("Cannot get interrupt line.\n"); | ||
2573 | PDEBUG("free circ_buf = %p size=%d", | ||
2574 | subdevice->circ_buf.buf, | ||
2575 | PAGE_SHIFT << ME4600_AO_CIRC_BUF_SIZE_ORDER); | ||
2576 | free_pages((unsigned long)subdevice->circ_buf.buf, | ||
2577 | ME4600_AO_CIRC_BUF_SIZE_ORDER); | ||
2578 | me_subdevice_deinit((me_subdevice_t *) subdevice); | ||
2579 | kfree(subdevice); | ||
2580 | return NULL; | ||
2581 | } | ||
2582 | PINFO("Registered irq=%d.\n", subdevice->irq); | ||
2583 | } else { | ||
2584 | subdevice->irq = 0; | ||
2585 | } | ||
2586 | |||
2587 | // Initialize registers. | ||
2588 | subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; | ||
2589 | subdevice->preload_reg = reg_base + ME4600_AO_SYNC_REG; | ||
2590 | if (ao_idx == 0) { | ||
2591 | subdevice->ctrl_reg = reg_base + ME4600_AO_00_CTRL_REG; | ||
2592 | subdevice->status_reg = reg_base + ME4600_AO_00_STATUS_REG; | ||
2593 | subdevice->fifo_reg = reg_base + ME4600_AO_00_FIFO_REG; | ||
2594 | subdevice->single_reg = reg_base + ME4600_AO_00_SINGLE_REG; | ||
2595 | subdevice->timer_reg = reg_base + ME4600_AO_00_TIMER_REG; | ||
2596 | subdevice->reg_base = reg_base; | ||
2597 | subdevice->bitpattern = 0; | ||
2598 | } else if (ao_idx == 1) { | ||
2599 | subdevice->ctrl_reg = reg_base + ME4600_AO_01_CTRL_REG; | ||
2600 | subdevice->status_reg = reg_base + ME4600_AO_01_STATUS_REG; | ||
2601 | subdevice->fifo_reg = reg_base + ME4600_AO_01_FIFO_REG; | ||
2602 | subdevice->single_reg = reg_base + ME4600_AO_01_SINGLE_REG; | ||
2603 | subdevice->timer_reg = reg_base + ME4600_AO_01_TIMER_REG; | ||
2604 | subdevice->reg_base = reg_base; | ||
2605 | subdevice->bitpattern = 0; | ||
2606 | } else if (ao_idx == 2) { | ||
2607 | subdevice->ctrl_reg = reg_base + ME4600_AO_02_CTRL_REG; | ||
2608 | subdevice->status_reg = reg_base + ME4600_AO_02_STATUS_REG; | ||
2609 | subdevice->fifo_reg = reg_base + ME4600_AO_02_FIFO_REG; | ||
2610 | subdevice->single_reg = reg_base + ME4600_AO_02_SINGLE_REG; | ||
2611 | subdevice->timer_reg = reg_base + ME4600_AO_02_TIMER_REG; | ||
2612 | subdevice->reg_base = reg_base; | ||
2613 | subdevice->bitpattern = 0; | ||
2614 | } else if (ao_idx == 3) { | ||
2615 | subdevice->ctrl_reg = reg_base + ME4600_AO_03_CTRL_REG; | ||
2616 | subdevice->status_reg = reg_base + ME4600_AO_03_STATUS_REG; | ||
2617 | subdevice->fifo_reg = reg_base + ME4600_AO_03_FIFO_REG; | ||
2618 | subdevice->single_reg = reg_base + ME4600_AO_03_SINGLE_REG; | ||
2619 | subdevice->timer_reg = reg_base + ME4600_AO_03_TIMER_REG; | ||
2620 | subdevice->reg_base = reg_base; | ||
2621 | subdevice->bitpattern = 1; | ||
2622 | } else { | ||
2623 | PERROR_CRITICAL("WRONG SUBDEVICE idx=%d!", ao_idx); | ||
2624 | me_subdevice_deinit((me_subdevice_t *) subdevice); | ||
2625 | if (subdevice->fifo) { | ||
2626 | free_pages((unsigned long)subdevice->circ_buf.buf, | ||
2627 | ME4600_AO_CIRC_BUF_SIZE_ORDER); | ||
2628 | } | ||
2629 | subdevice->circ_buf.buf = NULL; | ||
2630 | kfree(subdevice); | ||
2631 | return NULL; | ||
2632 | } | ||
2633 | |||
2634 | // Override base class methods. | ||
2635 | subdevice->base.me_subdevice_destructor = me4600_ao_destructor; | ||
2636 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
2637 | me4600_ao_io_reset_subdevice; | ||
2638 | subdevice->base.me_subdevice_io_single_config = | ||
2639 | me4600_ao_io_single_config; | ||
2640 | subdevice->base.me_subdevice_io_single_read = me4600_ao_io_single_read; | ||
2641 | subdevice->base.me_subdevice_io_single_write = | ||
2642 | me4600_ao_io_single_write; | ||
2643 | subdevice->base.me_subdevice_io_stream_config = | ||
2644 | me4600_ao_io_stream_config; | ||
2645 | subdevice->base.me_subdevice_io_stream_new_values = | ||
2646 | me4600_ao_io_stream_new_values; | ||
2647 | subdevice->base.me_subdevice_io_stream_write = | ||
2648 | me4600_ao_io_stream_write; | ||
2649 | subdevice->base.me_subdevice_io_stream_start = | ||
2650 | me4600_ao_io_stream_start; | ||
2651 | subdevice->base.me_subdevice_io_stream_status = | ||
2652 | me4600_ao_io_stream_status; | ||
2653 | subdevice->base.me_subdevice_io_stream_stop = me4600_ao_io_stream_stop; | ||
2654 | subdevice->base.me_subdevice_query_number_channels = | ||
2655 | me4600_ao_query_number_channels; | ||
2656 | subdevice->base.me_subdevice_query_subdevice_type = | ||
2657 | me4600_ao_query_subdevice_type; | ||
2658 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
2659 | me4600_ao_query_subdevice_caps; | ||
2660 | subdevice->base.me_subdevice_query_subdevice_caps_args = | ||
2661 | me4600_ao_query_subdevice_caps_args; | ||
2662 | subdevice->base.me_subdevice_query_range_by_min_max = | ||
2663 | me4600_ao_query_range_by_min_max; | ||
2664 | subdevice->base.me_subdevice_query_number_ranges = | ||
2665 | me4600_ao_query_number_ranges; | ||
2666 | subdevice->base.me_subdevice_query_range_info = | ||
2667 | me4600_ao_query_range_info; | ||
2668 | subdevice->base.me_subdevice_query_timer = me4600_ao_query_timer; | ||
2669 | |||
2670 | // Prepare work queue | ||
2671 | subdevice->me4600_workqueue = me4600_wq; | ||
2672 | |||
2673 | /* workqueue API changed in kernel 2.6.20 */ | ||
2674 | INIT_DELAYED_WORK(&subdevice->ao_control_task, | ||
2675 | me4600_ao_work_control_task); | ||
2676 | |||
2677 | if (subdevice->fifo) { // Set speed for single operations. | ||
2678 | outl(ME4600_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg); | ||
2679 | subdevice->hardware_stop_delay = HZ / 10; //100ms | ||
2680 | } | ||
2681 | |||
2682 | return subdevice; | ||
2683 | } | ||
2684 | |||
2685 | /** @brief Stop presentation. Preserve FIFOs. | ||
2686 | * | ||
2687 | * @param instance The subdevice instance (pointer). | ||
2688 | */ | ||
2689 | inline int ao_stop_immediately(me4600_ao_subdevice_t *instance) | ||
2690 | { | ||
2691 | unsigned long cpu_flags; | ||
2692 | uint32_t ctrl; | ||
2693 | int timeout; | ||
2694 | int i; | ||
2695 | |||
2696 | timeout = | ||
2697 | (instance->hardware_stop_delay > | ||
2698 | (HZ / 10)) ? instance->hardware_stop_delay : HZ / 10; | ||
2699 | for (i = 0; i <= timeout; i++) { | ||
2700 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2701 | // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! | ||
2702 | ctrl = inl(instance->ctrl_reg); | ||
2703 | ctrl |= | ||
2704 | ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ||
2705 | | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
2706 | ctrl &= | ||
2707 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
2708 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
2709 | outl(ctrl, instance->ctrl_reg); | ||
2710 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2711 | instance->reg_base, | ||
2712 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2713 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
2714 | |||
2715 | if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { // Exit. | ||
2716 | break; | ||
2717 | } | ||
2718 | //Still working! | ||
2719 | set_current_state(TASK_INTERRUPTIBLE); | ||
2720 | schedule_timeout(1); | ||
2721 | } | ||
2722 | |||
2723 | if (i > timeout) { | ||
2724 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
2725 | return ME_ERRNO_INTERNAL; | ||
2726 | } | ||
2727 | return ME_ERRNO_SUCCESS; | ||
2728 | } | ||
2729 | |||
2730 | /** @brief Copy data from circular buffer to fifo (fast) in wraparound. | ||
2731 | * @note This is time critical function. Checking is done at begining and end only. | ||
2732 | * @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. | ||
2733 | * | ||
2734 | * @param instance The subdevice instance (pointer). | ||
2735 | * @param count Maximum number of copied data. | ||
2736 | * @param start_pos Position of the firs value in buffer. | ||
2737 | * | ||
2738 | * @return On success: Number of copied data. | ||
2739 | * @return On error/success: 0. No datas were copied => no data in buffer. | ||
2740 | * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. | ||
2741 | */ | ||
2742 | inline int ao_write_data_wraparound(me4600_ao_subdevice_t *instance, int count, | ||
2743 | int start_pos) | ||
2744 | { /// @note This is time critical function! | ||
2745 | uint32_t status; | ||
2746 | uint32_t value; | ||
2747 | int pos = | ||
2748 | (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; | ||
2749 | int local_count = count; | ||
2750 | int i = 1; | ||
2751 | |||
2752 | if (count <= 0) { //Wrong count! | ||
2753 | return 0; | ||
2754 | } | ||
2755 | |||
2756 | while (i < local_count) { | ||
2757 | //Get value from buffer | ||
2758 | value = *(instance->circ_buf.buf + pos); | ||
2759 | //Prepare it | ||
2760 | if (instance->ao_idx & 0x1) { | ||
2761 | value <<= 16; | ||
2762 | } | ||
2763 | //Put value to FIFO | ||
2764 | outl(value, instance->fifo_reg); | ||
2765 | //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); | ||
2766 | |||
2767 | pos++; | ||
2768 | pos &= instance->circ_buf.mask; | ||
2769 | if (pos == instance->circ_buf.head) { | ||
2770 | pos = instance->circ_buf.tail; | ||
2771 | } | ||
2772 | i++; | ||
2773 | } | ||
2774 | |||
2775 | status = inl(instance->status_reg); | ||
2776 | if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! | ||
2777 | PERROR("FIFO was full before all datas were copied! idx=%d\n", | ||
2778 | instance->ao_idx); | ||
2779 | return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2780 | } else { //Add last value | ||
2781 | value = *(instance->circ_buf.buf + pos); | ||
2782 | if (instance->ao_idx & 0x1) { | ||
2783 | value <<= 16; | ||
2784 | } | ||
2785 | //Put value to FIFO | ||
2786 | outl(value, instance->fifo_reg); | ||
2787 | //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); | ||
2788 | } | ||
2789 | |||
2790 | PINFO("WRAPAROUND LOADED %d values. idx=%d\n", local_count, | ||
2791 | instance->ao_idx); | ||
2792 | return local_count; | ||
2793 | } | ||
2794 | |||
2795 | /** @brief Copy data from software buffer to fifo (fast). | ||
2796 | * @note This is time critical function. Checking is done at begining and end only. | ||
2797 | * @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. | ||
2798 | * | ||
2799 | * @param instance The subdevice instance (pointer). | ||
2800 | * @param count Maximum number of copied data. | ||
2801 | * @param start_pos Position of the firs value in buffer. | ||
2802 | * | ||
2803 | * @return On success: Number of copied data. | ||
2804 | * @return On error/success: 0. No datas were copied => no data in buffer. | ||
2805 | * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. | ||
2806 | */ | ||
2807 | inline int ao_write_data(me4600_ao_subdevice_t *instance, int count, | ||
2808 | int start_pos) | ||
2809 | { /// @note This is time critical function! | ||
2810 | uint32_t status; | ||
2811 | uint32_t value; | ||
2812 | int pos = | ||
2813 | (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; | ||
2814 | int local_count = count; | ||
2815 | int max_count; | ||
2816 | int i = 1; | ||
2817 | |||
2818 | if (count <= 0) { //Wrong count! | ||
2819 | return 0; | ||
2820 | } | ||
2821 | |||
2822 | max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; | ||
2823 | if (max_count <= 0) { //No data to copy! | ||
2824 | return 0; | ||
2825 | } | ||
2826 | |||
2827 | if (max_count < count) { | ||
2828 | local_count = max_count; | ||
2829 | } | ||
2830 | |||
2831 | while (i < local_count) { | ||
2832 | //Get value from buffer | ||
2833 | value = *(instance->circ_buf.buf + pos); | ||
2834 | //Prepare it | ||
2835 | if (instance->ao_idx & 0x1) { | ||
2836 | value <<= 16; | ||
2837 | } | ||
2838 | //Put value to FIFO | ||
2839 | outl(value, instance->fifo_reg); | ||
2840 | //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); | ||
2841 | |||
2842 | pos++; | ||
2843 | pos &= instance->circ_buf.mask; | ||
2844 | i++; | ||
2845 | } | ||
2846 | |||
2847 | status = inl(instance->status_reg); | ||
2848 | if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! | ||
2849 | PERROR("FIFO was full before all datas were copied! idx=%d\n", | ||
2850 | instance->ao_idx); | ||
2851 | return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2852 | } else { //Add last value | ||
2853 | value = *(instance->circ_buf.buf + pos); | ||
2854 | if (instance->ao_idx & 0x1) { | ||
2855 | value <<= 16; | ||
2856 | } | ||
2857 | //Put value to FIFO | ||
2858 | outl(value, instance->fifo_reg); | ||
2859 | //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); | ||
2860 | } | ||
2861 | |||
2862 | PINFO("FAST LOADED %d values. idx=%d\n", local_count, instance->ao_idx); | ||
2863 | return local_count; | ||
2864 | } | ||
2865 | |||
2866 | /** @brief Copy data from software buffer to fifo (slow). | ||
2867 | * @note This is slow function that copy all data from buffer to FIFO with full control. | ||
2868 | * | ||
2869 | * @param instance The subdevice instance (pointer). | ||
2870 | * @param count Maximum number of copied data. | ||
2871 | * @param start_pos Position of the firs value in buffer. | ||
2872 | * | ||
2873 | * @return On success: Number of copied values. | ||
2874 | * @return On error/success: 0. FIFO was full at begining. | ||
2875 | * @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW. | ||
2876 | */ | ||
2877 | inline int ao_write_data_pooling(me4600_ao_subdevice_t *instance, int count, | ||
2878 | int start_pos) | ||
2879 | { /// @note This is slow function! | ||
2880 | uint32_t status; | ||
2881 | uint32_t value; | ||
2882 | int pos = | ||
2883 | (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; | ||
2884 | int local_count = count; | ||
2885 | int i; | ||
2886 | int max_count; | ||
2887 | |||
2888 | if (count <= 0) { //Wrong count! | ||
2889 | PERROR("SLOW LOADED: Wrong count! idx=%d\n", instance->ao_idx); | ||
2890 | return 0; | ||
2891 | } | ||
2892 | |||
2893 | max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; | ||
2894 | if (max_count <= 0) { //No data to copy! | ||
2895 | PERROR("SLOW LOADED: No data to copy! idx=%d\n", | ||
2896 | instance->ao_idx); | ||
2897 | return 0; | ||
2898 | } | ||
2899 | |||
2900 | if (max_count < count) { | ||
2901 | local_count = max_count; | ||
2902 | } | ||
2903 | |||
2904 | for (i = 0; i < local_count; i++) { | ||
2905 | status = inl(instance->status_reg); | ||
2906 | if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full! | ||
2907 | return i; | ||
2908 | } | ||
2909 | //Get value from buffer | ||
2910 | value = *(instance->circ_buf.buf + pos); | ||
2911 | //Prepare it | ||
2912 | if (instance->ao_idx & 0x1) { | ||
2913 | value <<= 16; | ||
2914 | } | ||
2915 | //Put value to FIFO | ||
2916 | outl(value, instance->fifo_reg); | ||
2917 | //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); | ||
2918 | |||
2919 | pos++; | ||
2920 | pos &= instance->circ_buf.mask; | ||
2921 | } | ||
2922 | |||
2923 | PINFO("SLOW LOADED %d values. idx=%d\n", local_count, instance->ao_idx); | ||
2924 | return local_count; | ||
2925 | } | ||
2926 | |||
2927 | /** @brief Copy data from user space to circular buffer. | ||
2928 | * @param instance The subdevice instance (pointer). | ||
2929 | * @param count Number of datas in user space. | ||
2930 | * @param user_values Buffer's pointer. | ||
2931 | * | ||
2932 | * @return On success: Number of copied values. | ||
2933 | * @return On error: -ME_ERRNO_INTERNAL. | ||
2934 | */ | ||
2935 | inline int ao_get_data_from_user(me4600_ao_subdevice_t *instance, int count, | ||
2936 | int *user_values) | ||
2937 | { | ||
2938 | int i, err; | ||
2939 | int empty_space; | ||
2940 | int copied; | ||
2941 | int value; | ||
2942 | |||
2943 | empty_space = me_circ_buf_space(&instance->circ_buf); | ||
2944 | //We have only this space free. | ||
2945 | copied = (count < empty_space) ? count : empty_space; | ||
2946 | for (i = 0; i < copied; i++) { //Copy from user to buffer | ||
2947 | if ((err = get_user(value, (int *)(user_values + i)))) { | ||
2948 | PERROR | ||
2949 | ("BUFFER LOADED: get_user(0x%p) return an error: %d. idx=%d\n", | ||
2950 | user_values + i, err, instance->ao_idx); | ||
2951 | return -ME_ERRNO_INTERNAL; | ||
2952 | } | ||
2953 | /// @note The analog output in me4600 series has size of 16 bits. | ||
2954 | *(instance->circ_buf.buf + instance->circ_buf.head) = | ||
2955 | (uint16_t) value; | ||
2956 | instance->circ_buf.head++; | ||
2957 | instance->circ_buf.head &= instance->circ_buf.mask; | ||
2958 | } | ||
2959 | |||
2960 | PINFO("BUFFER LOADED %d values. idx=%d\n", copied, instance->ao_idx); | ||
2961 | return copied; | ||
2962 | } | ||
2963 | |||
2964 | /** @brief Checking actual hardware and logical state. | ||
2965 | * @param instance The subdevice instance (pointer). | ||
2966 | */ | ||
2967 | static void me4600_ao_work_control_task(struct work_struct *work) | ||
2968 | { | ||
2969 | me4600_ao_subdevice_t *instance; | ||
2970 | unsigned long cpu_flags = 0; | ||
2971 | uint32_t status; | ||
2972 | uint32_t ctrl; | ||
2973 | uint32_t synch; | ||
2974 | int reschedule = 0; | ||
2975 | int signaling = 0; | ||
2976 | |||
2977 | instance = | ||
2978 | container_of((void *)work, me4600_ao_subdevice_t, ao_control_task); | ||
2979 | PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, | ||
2980 | instance->ao_idx); | ||
2981 | |||
2982 | status = inl(instance->status_reg); | ||
2983 | PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
2984 | instance->status_reg - instance->reg_base, status); | ||
2985 | |||
2986 | switch (instance->status) { // Checking actual mode. | ||
2987 | |||
2988 | // Not configured for work. | ||
2989 | case ao_status_none: | ||
2990 | break; | ||
2991 | |||
2992 | //This are stable modes. No need to do anything. (?) | ||
2993 | case ao_status_single_configured: | ||
2994 | case ao_status_stream_configured: | ||
2995 | case ao_status_stream_fifo_error: | ||
2996 | case ao_status_stream_buffer_error: | ||
2997 | case ao_status_stream_error: | ||
2998 | PERROR("Shouldn't be running!.\n"); | ||
2999 | break; | ||
3000 | |||
3001 | case ao_status_stream_end: | ||
3002 | if (!instance->fifo) { | ||
3003 | PERROR_CRITICAL | ||
3004 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3005 | instance->status = ao_status_stream_error; | ||
3006 | // Signal the end. | ||
3007 | signaling = 1; | ||
3008 | break; | ||
3009 | } | ||
3010 | case ao_status_single_end: | ||
3011 | if (status & ME4600_AO_STATUS_BIT_FSM) { // State machine is working but the status is set to end. Force stop. | ||
3012 | |||
3013 | // Wait for stop. | ||
3014 | reschedule = 1; | ||
3015 | } | ||
3016 | |||
3017 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3018 | // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! | ||
3019 | ctrl = inl(instance->ctrl_reg); | ||
3020 | ctrl |= | ||
3021 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP | ||
3022 | | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
3023 | ctrl &= | ||
3024 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
3025 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
3026 | ctrl &= | ||
3027 | ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
3028 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); | ||
3029 | outl(ctrl, instance->ctrl_reg); | ||
3030 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3031 | instance->reg_base, | ||
3032 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
3033 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
3034 | break; | ||
3035 | |||
3036 | // Single modes | ||
3037 | case ao_status_single_run_wait: | ||
3038 | case ao_status_single_run: | ||
3039 | case ao_status_single_end_wait: | ||
3040 | |||
3041 | if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. | ||
3042 | if (((instance->fifo) | ||
3043 | && (!(status & ME4600_AO_STATUS_BIT_EF))) | ||
3044 | || (!(instance->fifo))) { // Single is in end state. | ||
3045 | PDEBUG("Single call has been complited.\n"); | ||
3046 | |||
3047 | // Set correct value for single_read(); | ||
3048 | instance->single_value = | ||
3049 | instance->single_value_in_fifo; | ||
3050 | |||
3051 | // Set status as 'ao_status_single_end' | ||
3052 | instance->status = ao_status_single_end; | ||
3053 | |||
3054 | // Signal the end. | ||
3055 | signaling = 1; | ||
3056 | // Wait for stop ISM. | ||
3057 | reschedule = 1; | ||
3058 | |||
3059 | break; | ||
3060 | } | ||
3061 | } | ||
3062 | // Check timeout. | ||
3063 | if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout | ||
3064 | PDEBUG("Timeout reached.\n"); | ||
3065 | // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! | ||
3066 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3067 | ctrl = inl(instance->ctrl_reg); | ||
3068 | ctrl |= | ||
3069 | ME4600_AO_CTRL_BIT_STOP | | ||
3070 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | | ||
3071 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
3072 | ctrl &= | ||
3073 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
3074 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
3075 | /// Fix for timeout error. | ||
3076 | ctrl &= | ||
3077 | ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
3078 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); | ||
3079 | if (instance->fifo) { //Disabling FIFO | ||
3080 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO; | ||
3081 | } | ||
3082 | outl(ctrl, instance->ctrl_reg); | ||
3083 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3084 | instance->reg_base, | ||
3085 | instance->ctrl_reg - instance->reg_base, | ||
3086 | ctrl); | ||
3087 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
3088 | cpu_flags); | ||
3089 | |||
3090 | spin_lock(instance->preload_reg_lock); | ||
3091 | //Remove from synchronous start. Block triggering from this output. | ||
3092 | synch = inl(instance->preload_reg); | ||
3093 | synch &= | ||
3094 | ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << | ||
3095 | instance->ao_idx); | ||
3096 | if (!(instance->fifo)) { // No FIFO - set to single safe mode | ||
3097 | synch |= | ||
3098 | ME4600_AO_SYNC_HOLD << instance->ao_idx; | ||
3099 | } | ||
3100 | outl(synch, instance->preload_reg); | ||
3101 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3102 | instance->reg_base, | ||
3103 | instance->preload_reg - instance->reg_base, | ||
3104 | synch); | ||
3105 | spin_unlock(instance->preload_reg_lock); | ||
3106 | |||
3107 | if (!(instance->fifo)) { // No FIFO | ||
3108 | // Restore old settings. | ||
3109 | PDEBUG("Write old value back to register.\n"); | ||
3110 | outl(instance->single_value, | ||
3111 | instance->single_reg); | ||
3112 | PDEBUG_REG | ||
3113 | ("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3114 | instance->reg_base, | ||
3115 | instance->single_reg - instance->reg_base, | ||
3116 | instance->single_value); | ||
3117 | } | ||
3118 | // Set correct value for single_read(); | ||
3119 | instance->single_value_in_fifo = instance->single_value; | ||
3120 | |||
3121 | instance->status = ao_status_single_end; | ||
3122 | |||
3123 | // Signal the end. | ||
3124 | signaling = 1; | ||
3125 | } | ||
3126 | // Wait for stop. | ||
3127 | reschedule = 1; | ||
3128 | break; | ||
3129 | |||
3130 | // Stream modes | ||
3131 | case ao_status_stream_run_wait: | ||
3132 | if (!instance->fifo) { | ||
3133 | PERROR_CRITICAL | ||
3134 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3135 | instance->status = ao_status_stream_error; | ||
3136 | // Signal the end. | ||
3137 | signaling = 1; | ||
3138 | break; | ||
3139 | } | ||
3140 | |||
3141 | if (status & ME4600_AO_STATUS_BIT_FSM) { // State machine is working. Waiting for start finish. | ||
3142 | instance->status = ao_status_stream_run; | ||
3143 | |||
3144 | // Signal end of this step | ||
3145 | signaling = 1; | ||
3146 | } else { // State machine is not working. | ||
3147 | if (!(status & ME4600_AO_STATUS_BIT_EF)) { // FIFO is empty. Procedure has started and finish already! | ||
3148 | instance->status = ao_status_stream_end; | ||
3149 | |||
3150 | // Signal the end. | ||
3151 | signaling = 1; | ||
3152 | // Wait for stop. | ||
3153 | reschedule = 1; | ||
3154 | break; | ||
3155 | } | ||
3156 | } | ||
3157 | |||
3158 | // Check timeout. | ||
3159 | if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout | ||
3160 | PDEBUG("Timeout reached.\n"); | ||
3161 | // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! | ||
3162 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3163 | ctrl = inl(instance->ctrl_reg); | ||
3164 | ctrl |= | ||
3165 | ME4600_AO_CTRL_BIT_STOP | | ||
3166 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | | ||
3167 | ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
3168 | ctrl &= | ||
3169 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
3170 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
3171 | outl(ctrl, instance->ctrl_reg); | ||
3172 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3173 | instance->reg_base, | ||
3174 | instance->ctrl_reg - instance->reg_base, | ||
3175 | ctrl); | ||
3176 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
3177 | cpu_flags); | ||
3178 | spin_lock(instance->preload_reg_lock); | ||
3179 | //Remove from synchronous start. Block triggering from this output. | ||
3180 | synch = inl(instance->preload_reg); | ||
3181 | synch &= | ||
3182 | ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << | ||
3183 | instance->ao_idx); | ||
3184 | outl(synch, instance->preload_reg); | ||
3185 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3186 | instance->reg_base, | ||
3187 | instance->preload_reg - instance->reg_base, | ||
3188 | synch); | ||
3189 | spin_unlock(instance->preload_reg_lock); | ||
3190 | |||
3191 | instance->status = ao_status_stream_end; | ||
3192 | |||
3193 | // Signal the end. | ||
3194 | signaling = 1; | ||
3195 | } | ||
3196 | // Wait for stop. | ||
3197 | reschedule = 1; | ||
3198 | break; | ||
3199 | |||
3200 | case ao_status_stream_run: | ||
3201 | if (!instance->fifo) { | ||
3202 | PERROR_CRITICAL | ||
3203 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3204 | instance->status = ao_status_stream_error; | ||
3205 | // Signal the end. | ||
3206 | signaling = 1; | ||
3207 | break; | ||
3208 | } | ||
3209 | |||
3210 | if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. This is an error. | ||
3211 | // BROKEN PIPE! | ||
3212 | if (!(status & ME4600_AO_STATUS_BIT_EF)) { // FIFO is empty. | ||
3213 | if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. | ||
3214 | if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. Requed data shown. | ||
3215 | PDEBUG | ||
3216 | ("ISM stoped. No data in FIFO. Buffer is not empty.\n"); | ||
3217 | instance->status = | ||
3218 | ao_status_stream_end; | ||
3219 | } else { | ||
3220 | PERROR | ||
3221 | ("Output stream has been broken. ISM stoped. No data in FIFO. Buffer is not empty.\n"); | ||
3222 | instance->status = | ||
3223 | ao_status_stream_buffer_error; | ||
3224 | } | ||
3225 | } else { // Software buffer is empty. | ||
3226 | PDEBUG | ||
3227 | ("ISM stoped. No data in FIFO. Buffer is empty.\n"); | ||
3228 | instance->status = ao_status_stream_end; | ||
3229 | } | ||
3230 | } else { // There are still datas in FIFO. | ||
3231 | if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. | ||
3232 | PERROR | ||
3233 | ("Output stream has been broken. ISM stoped but some data in FIFO and buffer.\n"); | ||
3234 | } else { // Software buffer is empty. | ||
3235 | PERROR | ||
3236 | ("Output stream has been broken. ISM stoped but some data in FIFO. Buffer is empty.\n"); | ||
3237 | } | ||
3238 | instance->status = ao_status_stream_fifo_error; | ||
3239 | |||
3240 | } | ||
3241 | |||
3242 | // Signal the failure. | ||
3243 | signaling = 1; | ||
3244 | break; | ||
3245 | } | ||
3246 | // Wait for stop. | ||
3247 | reschedule = 1; | ||
3248 | break; | ||
3249 | |||
3250 | case ao_status_stream_end_wait: | ||
3251 | if (!instance->fifo) { | ||
3252 | PERROR_CRITICAL | ||
3253 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3254 | instance->status = ao_status_stream_error; | ||
3255 | // Signal the end. | ||
3256 | signaling = 1; | ||
3257 | break; | ||
3258 | } | ||
3259 | |||
3260 | if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. Waiting for stop finish. | ||
3261 | instance->status = ao_status_stream_end; | ||
3262 | signaling = 1; | ||
3263 | } | ||
3264 | // State machine is working. | ||
3265 | reschedule = 1; | ||
3266 | break; | ||
3267 | |||
3268 | default: | ||
3269 | PERROR_CRITICAL("Status is in wrong state (%d)!\n", | ||
3270 | instance->status); | ||
3271 | instance->status = ao_status_stream_error; | ||
3272 | // Signal the end. | ||
3273 | signaling = 1; | ||
3274 | break; | ||
3275 | |||
3276 | } | ||
3277 | |||
3278 | if (signaling) { //Signal it. | ||
3279 | wake_up_interruptible_all(&instance->wait_queue); | ||
3280 | } | ||
3281 | |||
3282 | if (instance->ao_control_task_flag && reschedule) { // Reschedule task | ||
3283 | queue_delayed_work(instance->me4600_workqueue, | ||
3284 | &instance->ao_control_task, 1); | ||
3285 | } else { | ||
3286 | PINFO("<%s> Ending control task.\n", __func__); | ||
3287 | } | ||
3288 | |||
3289 | } | ||
3290 | #else | ||
3291 | /// @note SPECIAL BUILD FOR BOSCH | ||
3292 | /// @author Guenter Gebhardt | ||
3293 | static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, | ||
3294 | struct file *filep, int flags) | ||
3295 | { | ||
3296 | me4600_ao_subdevice_t *instance; | ||
3297 | int err = ME_ERRNO_SUCCESS; | ||
3298 | uint32_t tmp; | ||
3299 | unsigned long status; | ||
3300 | |||
3301 | PDEBUG("executed.\n"); | ||
3302 | |||
3303 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
3304 | |||
3305 | ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status); | ||
3306 | spin_lock(instance->preload_reg_lock); | ||
3307 | tmp = inl(instance->preload_reg); | ||
3308 | tmp &= ~(0x10001 << instance->ao_idx); | ||
3309 | outl(tmp, instance->preload_reg); | ||
3310 | *instance->preload_flags &= ~(0x1 << instance->ao_idx); | ||
3311 | spin_unlock(instance->preload_reg_lock); | ||
3312 | |||
3313 | tmp = inl(instance->ctrl_reg); | ||
3314 | tmp |= ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3315 | outl(tmp, instance->ctrl_reg); | ||
3316 | |||
3317 | while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ; | ||
3318 | |||
3319 | outl(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP, | ||
3320 | instance->ctrl_reg); | ||
3321 | |||
3322 | outl(0x8000, instance->single_reg); | ||
3323 | |||
3324 | instance->single_value = 0x8000; | ||
3325 | instance->circ_buf.head = 0; | ||
3326 | instance->circ_buf.tail = 0; | ||
3327 | |||
3328 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
3329 | |||
3330 | ME_SUBDEVICE_EXIT; | ||
3331 | |||
3332 | return err; | ||
3333 | } | ||
3334 | |||
3335 | static int me4600_ao_io_single_config(me_subdevice_t *subdevice, | ||
3336 | struct file *filep, | ||
3337 | int channel, | ||
3338 | int single_config, | ||
3339 | int ref, | ||
3340 | int trig_chan, | ||
3341 | int trig_type, int trig_edge, int flags) | ||
3342 | { | ||
3343 | me4600_ao_subdevice_t *instance; | ||
3344 | int err = ME_ERRNO_SUCCESS; | ||
3345 | uint32_t tmp; | ||
3346 | unsigned long cpu_flags; | ||
3347 | |||
3348 | PDEBUG("executed.\n"); | ||
3349 | |||
3350 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
3351 | |||
3352 | ME_SUBDEVICE_ENTER | ||
3353 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3354 | |||
3355 | if (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) { | ||
3356 | PERROR("Subdevice is busy.\n"); | ||
3357 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
3358 | goto ERROR; | ||
3359 | } | ||
3360 | |||
3361 | if (channel == 0) { | ||
3362 | if (single_config == 0) { | ||
3363 | if (ref == ME_REF_AO_GROUND) { | ||
3364 | if (trig_chan == ME_TRIG_CHAN_DEFAULT) { | ||
3365 | if (trig_type == ME_TRIG_TYPE_SW) { | ||
3366 | tmp = inl(instance->ctrl_reg); | ||
3367 | tmp |= | ||
3368 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3369 | outl(tmp, instance->ctrl_reg); | ||
3370 | tmp = | ||
3371 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3372 | outl(tmp, instance->ctrl_reg); | ||
3373 | |||
3374 | spin_lock(instance-> | ||
3375 | preload_reg_lock); | ||
3376 | tmp = | ||
3377 | inl(instance->preload_reg); | ||
3378 | tmp &= | ||
3379 | ~(0x10001 << instance-> | ||
3380 | ao_idx); | ||
3381 | outl(tmp, | ||
3382 | instance->preload_reg); | ||
3383 | *instance->preload_flags &= | ||
3384 | ~(0x1 << instance->ao_idx); | ||
3385 | spin_unlock(instance-> | ||
3386 | preload_reg_lock); | ||
3387 | } else if (trig_type == | ||
3388 | ME_TRIG_TYPE_EXT_DIGITAL) { | ||
3389 | if (trig_edge == | ||
3390 | ME_TRIG_EDGE_RISING) { | ||
3391 | tmp = | ||
3392 | inl(instance-> | ||
3393 | ctrl_reg); | ||
3394 | tmp |= | ||
3395 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3396 | outl(tmp, | ||
3397 | instance-> | ||
3398 | ctrl_reg); | ||
3399 | tmp = | ||
3400 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ||
3401 | | | ||
3402 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
3403 | outl(tmp, | ||
3404 | instance-> | ||
3405 | ctrl_reg); | ||
3406 | } else if (trig_edge == | ||
3407 | ME_TRIG_EDGE_FALLING) | ||
3408 | { | ||
3409 | tmp = | ||
3410 | inl(instance-> | ||
3411 | ctrl_reg); | ||
3412 | tmp |= | ||
3413 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3414 | outl(tmp, | ||
3415 | instance-> | ||
3416 | ctrl_reg); | ||
3417 | tmp = | ||
3418 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ||
3419 | | | ||
3420 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG | ||
3421 | | | ||
3422 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
3423 | outl(tmp, | ||
3424 | instance-> | ||
3425 | ctrl_reg); | ||
3426 | } else if (trig_edge == | ||
3427 | ME_TRIG_EDGE_ANY) { | ||
3428 | tmp = | ||
3429 | inl(instance-> | ||
3430 | ctrl_reg); | ||
3431 | tmp |= | ||
3432 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3433 | outl(tmp, | ||
3434 | instance-> | ||
3435 | ctrl_reg); | ||
3436 | tmp = | ||
3437 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ||
3438 | | | ||
3439 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG | ||
3440 | | | ||
3441 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ||
3442 | | | ||
3443 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
3444 | outl(tmp, | ||
3445 | instance-> | ||
3446 | ctrl_reg); | ||
3447 | } else { | ||
3448 | PERROR | ||
3449 | ("Invalid trigger edge.\n"); | ||
3450 | err = | ||
3451 | ME_ERRNO_INVALID_TRIG_EDGE; | ||
3452 | goto ERROR; | ||
3453 | } | ||
3454 | |||
3455 | spin_lock(instance-> | ||
3456 | preload_reg_lock); | ||
3457 | |||
3458 | tmp = | ||
3459 | inl(instance->preload_reg); | ||
3460 | tmp &= | ||
3461 | ~(0x10001 << instance-> | ||
3462 | ao_idx); | ||
3463 | tmp |= 0x1 << instance->ao_idx; | ||
3464 | outl(tmp, | ||
3465 | instance->preload_reg); | ||
3466 | *instance->preload_flags &= | ||
3467 | ~(0x1 << instance->ao_idx); | ||
3468 | spin_unlock(instance-> | ||
3469 | preload_reg_lock); | ||
3470 | } else { | ||
3471 | PERROR | ||
3472 | ("Invalid trigger type.\n"); | ||
3473 | err = | ||
3474 | ME_ERRNO_INVALID_TRIG_TYPE; | ||
3475 | goto ERROR; | ||
3476 | } | ||
3477 | } else if (trig_chan == | ||
3478 | ME_TRIG_CHAN_SYNCHRONOUS) { | ||
3479 | if (trig_type == ME_TRIG_TYPE_SW) { | ||
3480 | tmp = inl(instance->ctrl_reg); | ||
3481 | tmp |= | ||
3482 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3483 | outl(tmp, instance->ctrl_reg); | ||
3484 | tmp = | ||
3485 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3486 | outl(tmp, instance->ctrl_reg); | ||
3487 | |||
3488 | spin_lock(instance-> | ||
3489 | preload_reg_lock); | ||
3490 | tmp = | ||
3491 | inl(instance->preload_reg); | ||
3492 | tmp &= | ||
3493 | ~(0x10001 << instance-> | ||
3494 | ao_idx); | ||
3495 | tmp |= 0x1 << instance->ao_idx; | ||
3496 | outl(tmp, | ||
3497 | instance->preload_reg); | ||
3498 | *instance->preload_flags |= | ||
3499 | 0x1 << instance->ao_idx; | ||
3500 | spin_unlock(instance-> | ||
3501 | preload_reg_lock); | ||
3502 | } else if (trig_type == | ||
3503 | ME_TRIG_TYPE_EXT_DIGITAL) { | ||
3504 | if (trig_edge == | ||
3505 | ME_TRIG_EDGE_RISING) { | ||
3506 | tmp = | ||
3507 | inl(instance-> | ||
3508 | ctrl_reg); | ||
3509 | tmp |= | ||
3510 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3511 | outl(tmp, | ||
3512 | instance-> | ||
3513 | ctrl_reg); | ||
3514 | tmp = | ||
3515 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3516 | outl(tmp, | ||
3517 | instance-> | ||
3518 | ctrl_reg); | ||
3519 | } else if (trig_edge == | ||
3520 | ME_TRIG_EDGE_FALLING) | ||
3521 | { | ||
3522 | tmp = | ||
3523 | inl(instance-> | ||
3524 | ctrl_reg); | ||
3525 | tmp |= | ||
3526 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3527 | outl(tmp, | ||
3528 | instance-> | ||
3529 | ctrl_reg); | ||
3530 | tmp = | ||
3531 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ||
3532 | | | ||
3533 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
3534 | outl(tmp, | ||
3535 | instance-> | ||
3536 | ctrl_reg); | ||
3537 | } else if (trig_edge == | ||
3538 | ME_TRIG_EDGE_ANY) { | ||
3539 | tmp = | ||
3540 | inl(instance-> | ||
3541 | ctrl_reg); | ||
3542 | tmp |= | ||
3543 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3544 | outl(tmp, | ||
3545 | instance-> | ||
3546 | ctrl_reg); | ||
3547 | tmp = | ||
3548 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ||
3549 | | | ||
3550 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ||
3551 | | | ||
3552 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
3553 | outl(tmp, | ||
3554 | instance-> | ||
3555 | ctrl_reg); | ||
3556 | } else { | ||
3557 | PERROR | ||
3558 | ("Invalid trigger edge.\n"); | ||
3559 | err = | ||
3560 | ME_ERRNO_INVALID_TRIG_EDGE; | ||
3561 | goto ERROR; | ||
3562 | } | ||
3563 | |||
3564 | spin_lock(instance-> | ||
3565 | preload_reg_lock); | ||
3566 | |||
3567 | tmp = | ||
3568 | inl(instance->preload_reg); | ||
3569 | tmp |= | ||
3570 | 0x10001 << instance->ao_idx; | ||
3571 | outl(tmp, | ||
3572 | instance->preload_reg); | ||
3573 | *instance->preload_flags &= | ||
3574 | ~(0x1 << instance->ao_idx); | ||
3575 | spin_unlock(instance-> | ||
3576 | preload_reg_lock); | ||
3577 | } else { | ||
3578 | PERROR | ||
3579 | ("Invalid trigger type.\n"); | ||
3580 | err = | ||
3581 | ME_ERRNO_INVALID_TRIG_TYPE; | ||
3582 | goto ERROR; | ||
3583 | } | ||
3584 | } else { | ||
3585 | PERROR | ||
3586 | ("Invalid trigger channel specified.\n"); | ||
3587 | err = ME_ERRNO_INVALID_REF; | ||
3588 | goto ERROR; | ||
3589 | } | ||
3590 | } else { | ||
3591 | PERROR("Invalid analog reference specified.\n"); | ||
3592 | err = ME_ERRNO_INVALID_REF; | ||
3593 | goto ERROR; | ||
3594 | } | ||
3595 | } else { | ||
3596 | PERROR("Invalid single config specified.\n"); | ||
3597 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
3598 | goto ERROR; | ||
3599 | } | ||
3600 | } else { | ||
3601 | PERROR("Invalid channel number specified.\n"); | ||
3602 | err = ME_ERRNO_INVALID_CHANNEL; | ||
3603 | goto ERROR; | ||
3604 | } | ||
3605 | |||
3606 | ERROR: | ||
3607 | |||
3608 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
3609 | |||
3610 | ME_SUBDEVICE_EXIT; | ||
3611 | |||
3612 | return err; | ||
3613 | } | ||
3614 | |||
3615 | static int me4600_ao_io_single_read(me_subdevice_t *subdevice, | ||
3616 | struct file *filep, | ||
3617 | int channel, | ||
3618 | int *value, int time_out, int flags) | ||
3619 | { | ||
3620 | me4600_ao_subdevice_t *instance; | ||
3621 | int err = ME_ERRNO_SUCCESS; | ||
3622 | unsigned long tmp; | ||
3623 | unsigned long cpu_flags; | ||
3624 | |||
3625 | PDEBUG("executed.\n"); | ||
3626 | |||
3627 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
3628 | |||
3629 | if (channel != 0) { | ||
3630 | PERROR("Invalid channel number specified.\n"); | ||
3631 | return ME_ERRNO_INVALID_CHANNEL; | ||
3632 | } | ||
3633 | |||
3634 | ME_SUBDEVICE_ENTER | ||
3635 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3636 | tmp = inl(instance->ctrl_reg); | ||
3637 | |||
3638 | if (tmp & 0x3) { | ||
3639 | PERROR("Not in single mode.\n"); | ||
3640 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
3641 | } else { | ||
3642 | *value = instance->single_value; | ||
3643 | } | ||
3644 | |||
3645 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
3646 | |||
3647 | ME_SUBDEVICE_EXIT; | ||
3648 | |||
3649 | return err; | ||
3650 | } | ||
3651 | |||
3652 | static int me4600_ao_io_single_write(me_subdevice_t *subdevice, | ||
3653 | struct file *filep, | ||
3654 | int channel, | ||
3655 | int value, int time_out, int flags) | ||
3656 | { | ||
3657 | me4600_ao_subdevice_t *instance; | ||
3658 | int err = ME_ERRNO_SUCCESS; | ||
3659 | unsigned long mask = 0; | ||
3660 | unsigned long tmp; | ||
3661 | unsigned long cpu_flags; | ||
3662 | int i; | ||
3663 | wait_queue_head_t queue; | ||
3664 | unsigned long j; | ||
3665 | unsigned long delay = 0; | ||
3666 | |||
3667 | PDEBUG("executed.\n"); | ||
3668 | |||
3669 | init_waitqueue_head(&queue); | ||
3670 | |||
3671 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
3672 | |||
3673 | if (channel != 0) { | ||
3674 | PERROR("Invalid channel number specified.\n"); | ||
3675 | return ME_ERRNO_INVALID_CHANNEL; | ||
3676 | } | ||
3677 | |||
3678 | if (time_out < 0) { | ||
3679 | PERROR("Invalid timeout specified.\n"); | ||
3680 | return ME_ERRNO_INVALID_TIMEOUT; | ||
3681 | } | ||
3682 | |||
3683 | if (time_out) { | ||
3684 | delay = (time_out * HZ) / 1000; | ||
3685 | |||
3686 | if (delay == 0) | ||
3687 | delay = 1; | ||
3688 | } | ||
3689 | |||
3690 | ME_SUBDEVICE_ENTER | ||
3691 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3692 | |||
3693 | tmp = inl(instance->ctrl_reg); | ||
3694 | |||
3695 | if (tmp & 0x3) { | ||
3696 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
3697 | PERROR("Not in single mode.\n"); | ||
3698 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
3699 | goto ERROR; | ||
3700 | } | ||
3701 | |||
3702 | if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { | ||
3703 | outl(value, instance->single_reg); | ||
3704 | instance->single_value = value; | ||
3705 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
3706 | |||
3707 | if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { | ||
3708 | j = jiffies; | ||
3709 | |||
3710 | while (inl(instance->status_reg) & | ||
3711 | ME4600_AO_STATUS_BIT_FSM) { | ||
3712 | interruptible_sleep_on_timeout(&queue, 1); | ||
3713 | |||
3714 | if (signal_pending(current)) { | ||
3715 | PERROR | ||
3716 | ("Wait on external trigger interrupted by signal.\n"); | ||
3717 | err = ME_ERRNO_SIGNAL; | ||
3718 | goto ERROR; | ||
3719 | } | ||
3720 | |||
3721 | if (delay && ((jiffies - j) > delay)) { | ||
3722 | PERROR("Timeout reached.\n"); | ||
3723 | err = ME_ERRNO_TIMEOUT; | ||
3724 | goto ERROR; | ||
3725 | } | ||
3726 | } | ||
3727 | } | ||
3728 | } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) | ||
3729 | == (0x10001 << instance->ao_idx)) { | ||
3730 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { | ||
3731 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
3732 | outl(tmp, instance->ctrl_reg); | ||
3733 | outl(value, instance->single_reg); | ||
3734 | instance->single_value = value; | ||
3735 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
3736 | cpu_flags); | ||
3737 | |||
3738 | if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { | ||
3739 | j = jiffies; | ||
3740 | |||
3741 | while (inl(instance->status_reg) & | ||
3742 | ME4600_AO_STATUS_BIT_FSM) { | ||
3743 | interruptible_sleep_on_timeout(&queue, | ||
3744 | 1); | ||
3745 | |||
3746 | if (signal_pending(current)) { | ||
3747 | PERROR | ||
3748 | ("Wait on external trigger interrupted by signal.\n"); | ||
3749 | err = ME_ERRNO_SIGNAL; | ||
3750 | goto ERROR; | ||
3751 | } | ||
3752 | |||
3753 | if (delay && ((jiffies - j) > delay)) { | ||
3754 | PERROR("Timeout reached.\n"); | ||
3755 | err = ME_ERRNO_TIMEOUT; | ||
3756 | goto ERROR; | ||
3757 | } | ||
3758 | } | ||
3759 | } | ||
3760 | } else { | ||
3761 | outl(value, instance->single_reg); | ||
3762 | instance->single_value = value; | ||
3763 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
3764 | cpu_flags); | ||
3765 | } | ||
3766 | } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) | ||
3767 | == (0x1 << instance->ao_idx)) { | ||
3768 | outl(value, instance->single_reg); | ||
3769 | instance->single_value = value; | ||
3770 | |||
3771 | PDEBUG("Synchronous SW, flags = 0x%X.\n", flags); | ||
3772 | |||
3773 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { | ||
3774 | PDEBUG("Trigger synchronous SW.\n"); | ||
3775 | spin_lock(instance->preload_reg_lock); | ||
3776 | tmp = inl(instance->preload_reg); | ||
3777 | |||
3778 | for (i = 0; i < ME4600_AO_MAX_SUBDEVICES; i++) { | ||
3779 | if ((*instance->preload_flags & (0x1 << i))) { | ||
3780 | if ((tmp & (0x10001 << i)) == | ||
3781 | (0x1 << i)) { | ||
3782 | mask |= 0x1 << i; | ||
3783 | } | ||
3784 | } | ||
3785 | } | ||
3786 | |||
3787 | tmp &= ~(mask); | ||
3788 | |||
3789 | outl(tmp, instance->preload_reg); | ||
3790 | spin_unlock(instance->preload_reg_lock); | ||
3791 | } | ||
3792 | |||
3793 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
3794 | } else { | ||
3795 | outl(value, instance->single_reg); | ||
3796 | instance->single_value = value; | ||
3797 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
3798 | } | ||
3799 | |||
3800 | ERROR: | ||
3801 | |||
3802 | ME_SUBDEVICE_EXIT; | ||
3803 | |||
3804 | return err; | ||
3805 | } | ||
3806 | |||
3807 | static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, | ||
3808 | struct file *filep, | ||
3809 | meIOStreamConfig_t *config_list, | ||
3810 | int count, | ||
3811 | meIOStreamTrigger_t *trigger, | ||
3812 | int fifo_irq_threshold, int flags) | ||
3813 | { | ||
3814 | me4600_ao_subdevice_t *instance; | ||
3815 | int err = ME_ERRNO_SUCCESS; | ||
3816 | unsigned long ctrl; | ||
3817 | unsigned long tmp; | ||
3818 | unsigned long cpu_flags; | ||
3819 | uint64_t conv_ticks; | ||
3820 | unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; | ||
3821 | unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; | ||
3822 | |||
3823 | PDEBUG("executed.\n"); | ||
3824 | |||
3825 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
3826 | |||
3827 | conv_ticks = | ||
3828 | (uint64_t) conv_start_ticks_low + | ||
3829 | ((uint64_t) conv_start_ticks_high << 32); | ||
3830 | |||
3831 | if (!instance->fifo) { | ||
3832 | PERROR("Not a streaming ao.\n"); | ||
3833 | return ME_ERRNO_NOT_SUPPORTED; | ||
3834 | } | ||
3835 | |||
3836 | ME_SUBDEVICE_ENTER | ||
3837 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3838 | |||
3839 | if ((inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_FSM) { | ||
3840 | PERROR("Subdevice is busy.\n"); | ||
3841 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
3842 | goto ERROR; | ||
3843 | } | ||
3844 | |||
3845 | ctrl = inl(instance->ctrl_reg); | ||
3846 | ctrl |= ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3847 | outl(ctrl, instance->ctrl_reg); | ||
3848 | ctrl = ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3849 | outl(ctrl, instance->ctrl_reg); | ||
3850 | |||
3851 | if (count != 1) { | ||
3852 | PERROR("Invalid stream configuration list count specified.\n"); | ||
3853 | err = ME_ERRNO_INVALID_CONFIG_LIST_COUNT; | ||
3854 | goto ERROR; | ||
3855 | } | ||
3856 | |||
3857 | if (config_list[0].iChannel != 0) { | ||
3858 | PERROR("Invalid channel number specified.\n"); | ||
3859 | err = ME_ERRNO_INVALID_CHANNEL; | ||
3860 | goto ERROR; | ||
3861 | } | ||
3862 | |||
3863 | if (config_list[0].iStreamConfig != 0) { | ||
3864 | PERROR("Invalid stream config specified.\n"); | ||
3865 | err = ME_ERRNO_INVALID_STREAM_CONFIG; | ||
3866 | goto ERROR; | ||
3867 | } | ||
3868 | |||
3869 | if (config_list[0].iRef != ME_REF_AO_GROUND) { | ||
3870 | PERROR("Invalid analog reference.\n"); | ||
3871 | err = ME_ERRNO_INVALID_REF; | ||
3872 | goto ERROR; | ||
3873 | } | ||
3874 | |||
3875 | if ((trigger->iAcqStartTicksLow != 0) | ||
3876 | || (trigger->iAcqStartTicksHigh != 0)) { | ||
3877 | PERROR | ||
3878 | ("Invalid acquisition start trigger argument specified.\n"); | ||
3879 | err = ME_ERRNO_INVALID_ACQ_START_ARG; | ||
3880 | goto ERROR; | ||
3881 | } | ||
3882 | |||
3883 | switch (trigger->iAcqStartTrigType) { | ||
3884 | |||
3885 | case ME_TRIG_TYPE_SW: | ||
3886 | break; | ||
3887 | |||
3888 | case ME_TRIG_TYPE_EXT_DIGITAL: | ||
3889 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
3890 | |||
3891 | switch (trigger->iAcqStartTrigEdge) { | ||
3892 | |||
3893 | case ME_TRIG_EDGE_RISING: | ||
3894 | break; | ||
3895 | |||
3896 | case ME_TRIG_EDGE_FALLING: | ||
3897 | ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
3898 | |||
3899 | break; | ||
3900 | |||
3901 | case ME_TRIG_EDGE_ANY: | ||
3902 | ctrl |= | ||
3903 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
3904 | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
3905 | |||
3906 | break; | ||
3907 | |||
3908 | default: | ||
3909 | PERROR | ||
3910 | ("Invalid acquisition start trigger edge specified.\n"); | ||
3911 | |||
3912 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
3913 | |||
3914 | goto ERROR; | ||
3915 | |||
3916 | break; | ||
3917 | } | ||
3918 | |||
3919 | break; | ||
3920 | |||
3921 | default: | ||
3922 | PERROR("Invalid acquisition start trigger type specified.\n"); | ||
3923 | |||
3924 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; | ||
3925 | |||
3926 | goto ERROR; | ||
3927 | |||
3928 | break; | ||
3929 | } | ||
3930 | |||
3931 | switch (trigger->iScanStartTrigType) { | ||
3932 | |||
3933 | case ME_TRIG_TYPE_FOLLOW: | ||
3934 | break; | ||
3935 | |||
3936 | default: | ||
3937 | PERROR("Invalid scan start trigger type specified.\n"); | ||
3938 | |||
3939 | err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; | ||
3940 | |||
3941 | goto ERROR; | ||
3942 | |||
3943 | break; | ||
3944 | } | ||
3945 | |||
3946 | switch (trigger->iConvStartTrigType) { | ||
3947 | |||
3948 | case ME_TRIG_TYPE_TIMER: | ||
3949 | if ((conv_ticks < ME4600_AO_MIN_CHAN_TICKS) | ||
3950 | || (conv_ticks > ME4600_AO_MAX_CHAN_TICKS)) { | ||
3951 | PERROR | ||
3952 | ("Invalid conv start trigger argument specified.\n"); | ||
3953 | err = ME_ERRNO_INVALID_CONV_START_ARG; | ||
3954 | goto ERROR; | ||
3955 | } | ||
3956 | |||
3957 | break; | ||
3958 | |||
3959 | default: | ||
3960 | PERROR("Invalid conv start trigger type specified.\n"); | ||
3961 | |||
3962 | err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; | ||
3963 | |||
3964 | goto ERROR; | ||
3965 | |||
3966 | break; | ||
3967 | } | ||
3968 | |||
3969 | /* Preset to hardware wraparound mode */ | ||
3970 | instance->flags &= ~(ME4600_AO_FLAGS_SW_WRAP_MODE_MASK); | ||
3971 | |||
3972 | switch (trigger->iScanStopTrigType) { | ||
3973 | |||
3974 | case ME_TRIG_TYPE_NONE: | ||
3975 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
3976 | /* Set flags to indicate usage of software mode. */ | ||
3977 | instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_INF; | ||
3978 | instance->wrap_count = 0; | ||
3979 | instance->wrap_remaining = 0; | ||
3980 | } | ||
3981 | |||
3982 | break; | ||
3983 | |||
3984 | case ME_TRIG_TYPE_COUNT: | ||
3985 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
3986 | if (trigger->iScanStopCount <= 0) { | ||
3987 | PERROR("Invalid scan stop count specified.\n"); | ||
3988 | err = ME_ERRNO_INVALID_SCAN_STOP_ARG; | ||
3989 | goto ERROR; | ||
3990 | } | ||
3991 | |||
3992 | /* Set flags to indicate usage of software mode. */ | ||
3993 | instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_FIN; | ||
3994 | instance->wrap_count = trigger->iScanStopCount; | ||
3995 | instance->wrap_remaining = trigger->iScanStopCount; | ||
3996 | } else { | ||
3997 | PERROR("Invalid scan stop trigger type specified.\n"); | ||
3998 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
3999 | goto ERROR; | ||
4000 | } | ||
4001 | |||
4002 | break; | ||
4003 | |||
4004 | default: | ||
4005 | PERROR("Invalid scan stop trigger type specified.\n"); | ||
4006 | |||
4007 | err = ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; | ||
4008 | |||
4009 | goto ERROR; | ||
4010 | |||
4011 | break; | ||
4012 | } | ||
4013 | |||
4014 | switch (trigger->iAcqStopTrigType) { | ||
4015 | |||
4016 | case ME_TRIG_TYPE_NONE: | ||
4017 | break; | ||
4018 | |||
4019 | case ME_TRIG_TYPE_COUNT: | ||
4020 | if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { | ||
4021 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
4022 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
4023 | goto ERROR; | ||
4024 | } | ||
4025 | |||
4026 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
4027 | if (trigger->iAcqStopCount <= 0) { | ||
4028 | PERROR("Invalid acq stop count specified.\n"); | ||
4029 | err = ME_ERRNO_INVALID_ACQ_STOP_ARG; | ||
4030 | goto ERROR; | ||
4031 | } | ||
4032 | |||
4033 | /* Set flags to indicate usage of software mode. */ | ||
4034 | instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_FIN; | ||
4035 | instance->wrap_count = trigger->iAcqStopCount; | ||
4036 | instance->wrap_remaining = trigger->iAcqStopCount; | ||
4037 | } else { | ||
4038 | PERROR("Invalid acp stop trigger type specified.\n"); | ||
4039 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
4040 | goto ERROR; | ||
4041 | } | ||
4042 | |||
4043 | break; | ||
4044 | |||
4045 | default: | ||
4046 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
4047 | err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
4048 | goto ERROR; | ||
4049 | break; | ||
4050 | } | ||
4051 | |||
4052 | switch (trigger->iAcqStartTrigChan) { | ||
4053 | |||
4054 | case ME_TRIG_CHAN_DEFAULT: | ||
4055 | spin_lock(instance->preload_reg_lock); | ||
4056 | tmp = inl(instance->preload_reg); | ||
4057 | tmp &= ~(0x10001 << instance->ao_idx); | ||
4058 | outl(tmp, instance->preload_reg); | ||
4059 | spin_unlock(instance->preload_reg_lock); | ||
4060 | |||
4061 | break; | ||
4062 | |||
4063 | case ME_TRIG_CHAN_SYNCHRONOUS: | ||
4064 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { | ||
4065 | spin_lock(instance->preload_reg_lock); | ||
4066 | tmp = inl(instance->preload_reg); | ||
4067 | tmp &= ~(0x10001 << instance->ao_idx); | ||
4068 | outl(tmp, instance->preload_reg); | ||
4069 | tmp |= 0x1 << instance->ao_idx; | ||
4070 | outl(tmp, instance->preload_reg); | ||
4071 | spin_unlock(instance->preload_reg_lock); | ||
4072 | } else { | ||
4073 | ctrl &= ~(ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
4074 | spin_lock(instance->preload_reg_lock); | ||
4075 | tmp = inl(instance->preload_reg); | ||
4076 | tmp &= ~(0x10001 << instance->ao_idx); | ||
4077 | outl(tmp, instance->preload_reg); | ||
4078 | tmp |= 0x10000 << instance->ao_idx; | ||
4079 | outl(tmp, instance->preload_reg); | ||
4080 | spin_unlock(instance->preload_reg_lock); | ||
4081 | } | ||
4082 | |||
4083 | break; | ||
4084 | |||
4085 | default: | ||
4086 | PERROR("Invalid acq start trigger channel specified.\n"); | ||
4087 | err = ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; | ||
4088 | goto ERROR; | ||
4089 | |||
4090 | break; | ||
4091 | } | ||
4092 | |||
4093 | outl(conv_ticks - 2, instance->timer_reg); | ||
4094 | |||
4095 | if (flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) { | ||
4096 | if (instance->ao_idx == 3) { | ||
4097 | ctrl |= ME4600_AO_CTRL_BIT_ENABLE_DO; | ||
4098 | } else { | ||
4099 | err = ME_ERRNO_INVALID_FLAGS; | ||
4100 | goto ERROR; | ||
4101 | } | ||
4102 | } else { | ||
4103 | if (instance->ao_idx == 3) { | ||
4104 | ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_DO; | ||
4105 | } | ||
4106 | } | ||
4107 | |||
4108 | /* Set hardware mode. */ | ||
4109 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
4110 | ctrl |= ME4600_AO_CTRL_BIT_MODE_0; | ||
4111 | } else { | ||
4112 | ctrl |= ME4600_AO_CTRL_BIT_MODE_1; | ||
4113 | } | ||
4114 | |||
4115 | PDEBUG("Preload word = 0x%X.\n", inl(instance->preload_reg)); | ||
4116 | |||
4117 | PDEBUG("Ctrl word = 0x%lX.\n", ctrl); | ||
4118 | outl(ctrl, instance->ctrl_reg); // Write the control word | ||
4119 | |||
4120 | ERROR: | ||
4121 | |||
4122 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
4123 | |||
4124 | ME_SUBDEVICE_EXIT; | ||
4125 | |||
4126 | return err; | ||
4127 | } | ||
4128 | |||
4129 | static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, | ||
4130 | struct file *filep, | ||
4131 | int time_out, int *count, int flags) | ||
4132 | { | ||
4133 | me4600_ao_subdevice_t *instance; | ||
4134 | int err = ME_ERRNO_SUCCESS; | ||
4135 | long t = 0; | ||
4136 | long j; | ||
4137 | |||
4138 | PDEBUG("executed.\n"); | ||
4139 | |||
4140 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
4141 | |||
4142 | if (!instance->fifo) { | ||
4143 | PERROR("Not a streaming ao.\n"); | ||
4144 | return ME_ERRNO_NOT_SUPPORTED; | ||
4145 | } | ||
4146 | |||
4147 | if (time_out < 0) { | ||
4148 | PERROR("Invalid time_out specified.\n"); | ||
4149 | return ME_ERRNO_INVALID_TIMEOUT; | ||
4150 | } | ||
4151 | |||
4152 | if (time_out) { | ||
4153 | t = (time_out * HZ) / 1000; | ||
4154 | |||
4155 | if (t == 0) | ||
4156 | t = 1; | ||
4157 | } | ||
4158 | |||
4159 | *count = 0; | ||
4160 | |||
4161 | ME_SUBDEVICE_ENTER; | ||
4162 | |||
4163 | if (t) { | ||
4164 | j = jiffies; | ||
4165 | wait_event_interruptible_timeout(instance->wait_queue, | ||
4166 | ((me_circ_buf_space | ||
4167 | (&instance->circ_buf)) | ||
4168 | || !(inl(instance->status_reg) | ||
4169 | & | ||
4170 | ME4600_AO_STATUS_BIT_FSM)), | ||
4171 | t); | ||
4172 | |||
4173 | if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { | ||
4174 | PERROR("AO subdevice is not running.\n"); | ||
4175 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
4176 | } else if (signal_pending(current)) { | ||
4177 | PERROR("Wait on values interrupted from signal.\n"); | ||
4178 | err = ME_ERRNO_SIGNAL; | ||
4179 | } else if ((jiffies - j) >= t) { | ||
4180 | PERROR("Wait on values timed out.\n"); | ||
4181 | err = ME_ERRNO_TIMEOUT; | ||
4182 | } else { | ||
4183 | *count = me_circ_buf_space(&instance->circ_buf); | ||
4184 | } | ||
4185 | } else { | ||
4186 | wait_event_interruptible(instance->wait_queue, | ||
4187 | ((me_circ_buf_space | ||
4188 | (&instance->circ_buf)) | ||
4189 | || !(inl(instance->status_reg) & | ||
4190 | ME4600_AO_STATUS_BIT_FSM))); | ||
4191 | |||
4192 | if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { | ||
4193 | PERROR("AO subdevice is not running.\n"); | ||
4194 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
4195 | } else if (signal_pending(current)) { | ||
4196 | PERROR("Wait on values interrupted from signal.\n"); | ||
4197 | err = ME_ERRNO_SIGNAL; | ||
4198 | } else { | ||
4199 | *count = me_circ_buf_space(&instance->circ_buf); | ||
4200 | } | ||
4201 | } | ||
4202 | |||
4203 | ME_SUBDEVICE_EXIT; | ||
4204 | |||
4205 | return err; | ||
4206 | } | ||
4207 | |||
4208 | static void stop_immediately(me4600_ao_subdevice_t *instance) | ||
4209 | { | ||
4210 | unsigned long cpu_flags; | ||
4211 | uint32_t tmp; | ||
4212 | |||
4213 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
4214 | tmp = inl(instance->ctrl_reg); | ||
4215 | tmp |= ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
4216 | outl(tmp, instance->ctrl_reg); | ||
4217 | |||
4218 | while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ; | ||
4219 | |||
4220 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
4221 | } | ||
4222 | |||
4223 | static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, | ||
4224 | struct file *filep, | ||
4225 | int start_mode, int time_out, int flags) | ||
4226 | { | ||
4227 | me4600_ao_subdevice_t *instance; | ||
4228 | int err = ME_ERRNO_SUCCESS; | ||
4229 | unsigned long cpu_flags = 0; | ||
4230 | unsigned long ref; | ||
4231 | unsigned long tmp; | ||
4232 | unsigned long delay = 0; | ||
4233 | wait_queue_head_t queue; | ||
4234 | |||
4235 | PDEBUG("executed.\n"); | ||
4236 | |||
4237 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
4238 | |||
4239 | init_waitqueue_head(&queue); | ||
4240 | |||
4241 | if (time_out < 0) { | ||
4242 | PERROR("Invalid timeout specified.\n"); | ||
4243 | return ME_ERRNO_INVALID_TIMEOUT; | ||
4244 | } | ||
4245 | |||
4246 | if (time_out) { | ||
4247 | delay = (time_out * HZ) / 1000; | ||
4248 | |||
4249 | if (delay == 0) | ||
4250 | delay = 1; | ||
4251 | } | ||
4252 | |||
4253 | if (!instance->fifo) { | ||
4254 | PERROR("Not a streaming ao.\n"); | ||
4255 | return ME_ERRNO_NOT_SUPPORTED; | ||
4256 | } | ||
4257 | |||
4258 | ME_SUBDEVICE_ENTER | ||
4259 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
4260 | |||
4261 | tmp = inl(instance->ctrl_reg); | ||
4262 | |||
4263 | switch (tmp & (ME4600_AO_CTRL_MASK_MODE)) { | ||
4264 | |||
4265 | case 0: // Single mode | ||
4266 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
4267 | PERROR("Subdevice is configured in single mode.\n"); | ||
4268 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
4269 | goto ERROR; | ||
4270 | |||
4271 | case 1: // Wraparound mode | ||
4272 | if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { // Normal wraparound with external trigger | ||
4273 | |||
4274 | if ((inl(instance->status_reg) & | ||
4275 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4276 | spin_unlock_irqrestore(&instance-> | ||
4277 | subdevice_lock, | ||
4278 | cpu_flags); | ||
4279 | PERROR("Conversion is already running.\n"); | ||
4280 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4281 | goto ERROR; | ||
4282 | } | ||
4283 | |||
4284 | tmp &= | ||
4285 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
4286 | ME4600_AO_CTRL_BIT_STOP | | ||
4287 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4288 | |||
4289 | outl(tmp, instance->ctrl_reg); | ||
4290 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
4291 | cpu_flags); | ||
4292 | |||
4293 | if (start_mode == ME_START_MODE_BLOCKING) { | ||
4294 | init_waitqueue_head(&queue); | ||
4295 | |||
4296 | if (delay) { | ||
4297 | ref = jiffies; | ||
4298 | |||
4299 | while (! | ||
4300 | (inl(instance->status_reg) & | ||
4301 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4302 | interruptible_sleep_on_timeout | ||
4303 | (&queue, 1); | ||
4304 | |||
4305 | if (signal_pending(current)) { | ||
4306 | PERROR | ||
4307 | ("Wait on start of state machine interrupted.\n"); | ||
4308 | stop_immediately | ||
4309 | (instance); | ||
4310 | err = ME_ERRNO_SIGNAL; | ||
4311 | goto ERROR; | ||
4312 | } | ||
4313 | |||
4314 | if (((jiffies - ref) >= delay)) { | ||
4315 | PERROR | ||
4316 | ("Timeout reached.\n"); | ||
4317 | stop_immediately | ||
4318 | (instance); | ||
4319 | err = ME_ERRNO_TIMEOUT; | ||
4320 | goto ERROR; | ||
4321 | } | ||
4322 | } | ||
4323 | } else { | ||
4324 | while (! | ||
4325 | (inl(instance->status_reg) & | ||
4326 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4327 | interruptible_sleep_on_timeout | ||
4328 | (&queue, 1); | ||
4329 | |||
4330 | if (signal_pending(current)) { | ||
4331 | PERROR | ||
4332 | ("Wait on start of state machine interrupted.\n"); | ||
4333 | stop_immediately | ||
4334 | (instance); | ||
4335 | err = ME_ERRNO_SIGNAL; | ||
4336 | goto ERROR; | ||
4337 | } | ||
4338 | } | ||
4339 | } | ||
4340 | } else if (start_mode == ME_START_MODE_NONBLOCKING) { | ||
4341 | } else { | ||
4342 | PERROR("Invalid start mode specified.\n"); | ||
4343 | err = ME_ERRNO_INVALID_START_MODE; | ||
4344 | goto ERROR; | ||
4345 | } | ||
4346 | } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x10000 << instance->ao_idx)) { // Synchronous with external trigger | ||
4347 | |||
4348 | if ((inl(instance->status_reg) & | ||
4349 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4350 | spin_unlock_irqrestore(&instance-> | ||
4351 | subdevice_lock, | ||
4352 | cpu_flags); | ||
4353 | PERROR("Conversion is already running.\n"); | ||
4354 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4355 | goto ERROR; | ||
4356 | } | ||
4357 | |||
4358 | if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { | ||
4359 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
4360 | tmp &= | ||
4361 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
4362 | ME4600_AO_CTRL_BIT_STOP | | ||
4363 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4364 | outl(tmp, instance->ctrl_reg); | ||
4365 | spin_unlock_irqrestore(&instance-> | ||
4366 | subdevice_lock, | ||
4367 | cpu_flags); | ||
4368 | |||
4369 | if (start_mode == ME_START_MODE_BLOCKING) { | ||
4370 | init_waitqueue_head(&queue); | ||
4371 | |||
4372 | if (delay) { | ||
4373 | ref = jiffies; | ||
4374 | |||
4375 | while (! | ||
4376 | (inl | ||
4377 | (instance-> | ||
4378 | status_reg) & | ||
4379 | ME4600_AO_STATUS_BIT_FSM)) | ||
4380 | { | ||
4381 | interruptible_sleep_on_timeout | ||
4382 | (&queue, 1); | ||
4383 | |||
4384 | if (signal_pending | ||
4385 | (current)) { | ||
4386 | PERROR | ||
4387 | ("Wait on start of state machine interrupted.\n"); | ||
4388 | stop_immediately | ||
4389 | (instance); | ||
4390 | err = | ||
4391 | ME_ERRNO_SIGNAL; | ||
4392 | goto ERROR; | ||
4393 | } | ||
4394 | |||
4395 | if (((jiffies - ref) >= | ||
4396 | delay)) { | ||
4397 | PERROR | ||
4398 | ("Timeout reached.\n"); | ||
4399 | stop_immediately | ||
4400 | (instance); | ||
4401 | err = | ||
4402 | ME_ERRNO_TIMEOUT; | ||
4403 | goto ERROR; | ||
4404 | } | ||
4405 | } | ||
4406 | } else { | ||
4407 | while (! | ||
4408 | (inl | ||
4409 | (instance-> | ||
4410 | status_reg) & | ||
4411 | ME4600_AO_STATUS_BIT_FSM)) | ||
4412 | { | ||
4413 | interruptible_sleep_on_timeout | ||
4414 | (&queue, 1); | ||
4415 | |||
4416 | if (signal_pending | ||
4417 | (current)) { | ||
4418 | PERROR | ||
4419 | ("Wait on start of state machine interrupted.\n"); | ||
4420 | stop_immediately | ||
4421 | (instance); | ||
4422 | err = | ||
4423 | ME_ERRNO_SIGNAL; | ||
4424 | goto ERROR; | ||
4425 | } | ||
4426 | } | ||
4427 | } | ||
4428 | } else if (start_mode == | ||
4429 | ME_START_MODE_NONBLOCKING) { | ||
4430 | } else { | ||
4431 | PERROR | ||
4432 | ("Invalid start mode specified.\n"); | ||
4433 | err = ME_ERRNO_INVALID_START_MODE; | ||
4434 | goto ERROR; | ||
4435 | } | ||
4436 | } else { | ||
4437 | tmp &= | ||
4438 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
4439 | ME4600_AO_CTRL_BIT_STOP | | ||
4440 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4441 | outl(tmp, instance->ctrl_reg); | ||
4442 | spin_unlock_irqrestore(&instance-> | ||
4443 | subdevice_lock, | ||
4444 | cpu_flags); | ||
4445 | } | ||
4446 | } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x1 << instance->ao_idx)) { // Synchronous wraparound with sw trigger | ||
4447 | |||
4448 | if ((inl(instance->status_reg) & | ||
4449 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4450 | spin_unlock_irqrestore(&instance-> | ||
4451 | subdevice_lock, | ||
4452 | cpu_flags); | ||
4453 | PERROR("Conversion is already running.\n"); | ||
4454 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4455 | goto ERROR; | ||
4456 | } | ||
4457 | |||
4458 | tmp &= | ||
4459 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
4460 | ME4600_AO_CTRL_BIT_STOP | | ||
4461 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4462 | |||
4463 | outl(tmp, instance->ctrl_reg); | ||
4464 | |||
4465 | if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { | ||
4466 | outl(0x8000, instance->single_reg); | ||
4467 | instance->single_value = 0x8000; | ||
4468 | } | ||
4469 | |||
4470 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
4471 | cpu_flags); | ||
4472 | } else { // Software start | ||
4473 | |||
4474 | if ((inl(instance->status_reg) & | ||
4475 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4476 | spin_unlock_irqrestore(&instance-> | ||
4477 | subdevice_lock, | ||
4478 | cpu_flags); | ||
4479 | PERROR("Conversion is already running.\n"); | ||
4480 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4481 | goto ERROR; | ||
4482 | } | ||
4483 | |||
4484 | tmp &= | ||
4485 | ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | | ||
4486 | ME4600_AO_CTRL_BIT_STOP | | ||
4487 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4488 | |||
4489 | outl(tmp, instance->ctrl_reg); | ||
4490 | |||
4491 | outl(0x8000, instance->single_reg); | ||
4492 | instance->single_value = 0x8000; | ||
4493 | |||
4494 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
4495 | cpu_flags); | ||
4496 | } | ||
4497 | |||
4498 | break; | ||
4499 | |||
4500 | case 2: // Continuous mode | ||
4501 | if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { // Externally triggered | ||
4502 | |||
4503 | if ((inl(instance->status_reg) & | ||
4504 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4505 | spin_unlock_irqrestore(&instance-> | ||
4506 | subdevice_lock, | ||
4507 | cpu_flags); | ||
4508 | PERROR("Conversion is already running.\n"); | ||
4509 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4510 | goto ERROR; | ||
4511 | } | ||
4512 | |||
4513 | tmp &= | ||
4514 | ~(ME4600_AO_CTRL_BIT_STOP | | ||
4515 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4516 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
4517 | outl(tmp, instance->ctrl_reg); | ||
4518 | instance->wrap_remaining = instance->wrap_count; | ||
4519 | instance->circ_buf.tail = 0; | ||
4520 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
4521 | cpu_flags); | ||
4522 | |||
4523 | if (start_mode == ME_START_MODE_BLOCKING) { | ||
4524 | init_waitqueue_head(&queue); | ||
4525 | |||
4526 | if (delay) { | ||
4527 | ref = jiffies; | ||
4528 | |||
4529 | while (! | ||
4530 | (inl(instance->status_reg) & | ||
4531 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4532 | interruptible_sleep_on_timeout | ||
4533 | (&queue, 1); | ||
4534 | |||
4535 | if (signal_pending(current)) { | ||
4536 | PERROR | ||
4537 | ("Wait on start of state machine interrupted.\n"); | ||
4538 | stop_immediately | ||
4539 | (instance); | ||
4540 | err = ME_ERRNO_SIGNAL; | ||
4541 | goto ERROR; | ||
4542 | } | ||
4543 | |||
4544 | if (((jiffies - ref) >= delay)) { | ||
4545 | PERROR | ||
4546 | ("Timeout reached.\n"); | ||
4547 | stop_immediately | ||
4548 | (instance); | ||
4549 | err = ME_ERRNO_TIMEOUT; | ||
4550 | goto ERROR; | ||
4551 | } | ||
4552 | } | ||
4553 | } else { | ||
4554 | while (! | ||
4555 | (inl(instance->status_reg) & | ||
4556 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4557 | interruptible_sleep_on_timeout | ||
4558 | (&queue, 1); | ||
4559 | |||
4560 | if (signal_pending(current)) { | ||
4561 | PERROR | ||
4562 | ("Wait on start of state machine interrupted.\n"); | ||
4563 | stop_immediately | ||
4564 | (instance); | ||
4565 | err = ME_ERRNO_SIGNAL; | ||
4566 | goto ERROR; | ||
4567 | } | ||
4568 | } | ||
4569 | } | ||
4570 | } else if (start_mode == ME_START_MODE_NONBLOCKING) { | ||
4571 | /* Do nothing */ | ||
4572 | } else { | ||
4573 | PERROR("Invalid start mode specified.\n"); | ||
4574 | stop_immediately(instance); | ||
4575 | err = ME_ERRNO_INVALID_START_MODE; | ||
4576 | goto ERROR; | ||
4577 | } | ||
4578 | } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x10000 << instance->ao_idx)) { // Synchronous with external trigger | ||
4579 | |||
4580 | if ((inl(instance->status_reg) & | ||
4581 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4582 | spin_unlock_irqrestore(&instance-> | ||
4583 | subdevice_lock, | ||
4584 | cpu_flags); | ||
4585 | PERROR("Conversion is already running.\n"); | ||
4586 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4587 | goto ERROR; | ||
4588 | } | ||
4589 | |||
4590 | if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { | ||
4591 | tmp |= | ||
4592 | ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG | | ||
4593 | ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
4594 | tmp &= | ||
4595 | ~(ME4600_AO_CTRL_BIT_STOP | | ||
4596 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4597 | outl(tmp, instance->ctrl_reg); | ||
4598 | instance->wrap_remaining = instance->wrap_count; | ||
4599 | instance->circ_buf.tail = 0; | ||
4600 | |||
4601 | spin_unlock_irqrestore(&instance-> | ||
4602 | subdevice_lock, | ||
4603 | cpu_flags); | ||
4604 | |||
4605 | if (start_mode == ME_START_MODE_BLOCKING) { | ||
4606 | init_waitqueue_head(&queue); | ||
4607 | |||
4608 | if (delay) { | ||
4609 | ref = jiffies; | ||
4610 | |||
4611 | while (! | ||
4612 | (inl | ||
4613 | (instance-> | ||
4614 | status_reg) & | ||
4615 | ME4600_AO_STATUS_BIT_FSM)) | ||
4616 | { | ||
4617 | interruptible_sleep_on_timeout | ||
4618 | (&queue, 1); | ||
4619 | |||
4620 | if (signal_pending | ||
4621 | (current)) { | ||
4622 | PERROR | ||
4623 | ("Wait on start of state machine interrupted.\n"); | ||
4624 | stop_immediately | ||
4625 | (instance); | ||
4626 | err = | ||
4627 | ME_ERRNO_SIGNAL; | ||
4628 | goto ERROR; | ||
4629 | } | ||
4630 | |||
4631 | if (((jiffies - ref) >= | ||
4632 | delay)) { | ||
4633 | PERROR | ||
4634 | ("Timeout reached.\n"); | ||
4635 | stop_immediately | ||
4636 | (instance); | ||
4637 | err = | ||
4638 | ME_ERRNO_TIMEOUT; | ||
4639 | goto ERROR; | ||
4640 | } | ||
4641 | } | ||
4642 | } else { | ||
4643 | while (! | ||
4644 | (inl | ||
4645 | (instance-> | ||
4646 | status_reg) & | ||
4647 | ME4600_AO_STATUS_BIT_FSM)) | ||
4648 | { | ||
4649 | interruptible_sleep_on_timeout | ||
4650 | (&queue, 1); | ||
4651 | |||
4652 | if (signal_pending | ||
4653 | (current)) { | ||
4654 | PERROR | ||
4655 | ("Wait on start of state machine interrupted.\n"); | ||
4656 | stop_immediately | ||
4657 | (instance); | ||
4658 | err = | ||
4659 | ME_ERRNO_SIGNAL; | ||
4660 | goto ERROR; | ||
4661 | } | ||
4662 | } | ||
4663 | } | ||
4664 | } else if (start_mode == | ||
4665 | ME_START_MODE_NONBLOCKING) { | ||
4666 | } else { | ||
4667 | PERROR | ||
4668 | ("Invalid start mode specified.\n"); | ||
4669 | stop_immediately(instance); | ||
4670 | err = ME_ERRNO_INVALID_START_MODE; | ||
4671 | goto ERROR; | ||
4672 | } | ||
4673 | } else { | ||
4674 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
4675 | tmp &= | ||
4676 | ~(ME4600_AO_CTRL_BIT_STOP | | ||
4677 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4678 | outl(tmp, instance->ctrl_reg); | ||
4679 | instance->wrap_remaining = instance->wrap_count; | ||
4680 | instance->circ_buf.tail = 0; | ||
4681 | spin_unlock_irqrestore(&instance-> | ||
4682 | subdevice_lock, | ||
4683 | cpu_flags); | ||
4684 | } | ||
4685 | } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x1 << instance->ao_idx)) { // Synchronous wraparound with sw trigger | ||
4686 | |||
4687 | if ((inl(instance->status_reg) & | ||
4688 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4689 | spin_unlock_irqrestore(&instance-> | ||
4690 | subdevice_lock, | ||
4691 | cpu_flags); | ||
4692 | PERROR("Conversion is already running.\n"); | ||
4693 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4694 | goto ERROR; | ||
4695 | } | ||
4696 | |||
4697 | tmp &= | ||
4698 | ~(ME4600_AO_CTRL_BIT_STOP | | ||
4699 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4700 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
4701 | instance->wrap_remaining = instance->wrap_count; | ||
4702 | instance->circ_buf.tail = 0; | ||
4703 | PDEBUG("CTRL Reg = 0x%X.\n", inl(instance->ctrl_reg)); | ||
4704 | outl(tmp, instance->ctrl_reg); | ||
4705 | |||
4706 | if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { | ||
4707 | outl(0x8000, instance->single_reg); | ||
4708 | instance->single_value = 0x8000; | ||
4709 | } | ||
4710 | |||
4711 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
4712 | cpu_flags); | ||
4713 | } else { // Software start | ||
4714 | |||
4715 | if ((inl(instance->status_reg) & | ||
4716 | ME4600_AO_STATUS_BIT_FSM)) { | ||
4717 | spin_unlock_irqrestore(&instance-> | ||
4718 | subdevice_lock, | ||
4719 | cpu_flags); | ||
4720 | PERROR("Conversion is already running.\n"); | ||
4721 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4722 | goto ERROR; | ||
4723 | } | ||
4724 | |||
4725 | tmp &= | ||
4726 | ~(ME4600_AO_CTRL_BIT_STOP | | ||
4727 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
4728 | |||
4729 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
4730 | outl(tmp, instance->ctrl_reg); | ||
4731 | outl(0x8000, instance->single_reg); | ||
4732 | instance->single_value = 0x8000; | ||
4733 | instance->wrap_remaining = instance->wrap_count; | ||
4734 | instance->circ_buf.tail = 0; | ||
4735 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
4736 | cpu_flags); | ||
4737 | } | ||
4738 | |||
4739 | break; | ||
4740 | |||
4741 | default: | ||
4742 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
4743 | PERROR("Invalid mode configured.\n"); | ||
4744 | err = ME_ERRNO_INTERNAL; | ||
4745 | goto ERROR; | ||
4746 | } | ||
4747 | |||
4748 | ERROR: | ||
4749 | |||
4750 | ME_SUBDEVICE_EXIT; | ||
4751 | |||
4752 | return err; | ||
4753 | } | ||
4754 | |||
4755 | static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, | ||
4756 | struct file *filep, | ||
4757 | int wait, | ||
4758 | int *status, int *values, int flags) | ||
4759 | { | ||
4760 | me4600_ao_subdevice_t *instance; | ||
4761 | int err = ME_ERRNO_SUCCESS; | ||
4762 | wait_queue_head_t queue; | ||
4763 | |||
4764 | PDEBUG("executed.\n"); | ||
4765 | |||
4766 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
4767 | |||
4768 | init_waitqueue_head(&queue); | ||
4769 | |||
4770 | if (!instance->fifo) { | ||
4771 | PERROR("Not a streaming ao.\n"); | ||
4772 | return ME_ERRNO_NOT_SUPPORTED; | ||
4773 | } | ||
4774 | |||
4775 | ME_SUBDEVICE_ENTER; | ||
4776 | |||
4777 | if (wait == ME_WAIT_NONE) { | ||
4778 | *status = | ||
4779 | (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ? | ||
4780 | ME_STATUS_BUSY : ME_STATUS_IDLE; | ||
4781 | *values = me_circ_buf_space(&instance->circ_buf); | ||
4782 | } else if (wait == ME_WAIT_IDLE) { | ||
4783 | while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) { | ||
4784 | interruptible_sleep_on_timeout(&queue, 1); | ||
4785 | |||
4786 | if (instance->flags & ME4600_AO_FLAGS_BROKEN_PIPE) { | ||
4787 | PERROR("Output stream was interrupted.\n"); | ||
4788 | *status = ME_STATUS_ERROR; | ||
4789 | err = ME_ERRNO_SUCCESS; | ||
4790 | goto ERROR; | ||
4791 | } | ||
4792 | |||
4793 | if (signal_pending(current)) { | ||
4794 | PERROR | ||
4795 | ("Wait on state machine interrupted by signal.\n"); | ||
4796 | *status = ME_STATUS_INVALID; | ||
4797 | err = ME_ERRNO_SIGNAL; | ||
4798 | goto ERROR; | ||
4799 | } | ||
4800 | } | ||
4801 | |||
4802 | *status = ME_STATUS_IDLE; | ||
4803 | |||
4804 | *values = me_circ_buf_space(&instance->circ_buf); | ||
4805 | } else { | ||
4806 | PERROR("Invalid wait argument specified.\n"); | ||
4807 | *status = ME_STATUS_INVALID; | ||
4808 | err = ME_ERRNO_INVALID_WAIT; | ||
4809 | goto ERROR; | ||
4810 | } | ||
4811 | |||
4812 | ERROR: | ||
4813 | |||
4814 | ME_SUBDEVICE_EXIT; | ||
4815 | |||
4816 | return err; | ||
4817 | } | ||
4818 | |||
4819 | static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, | ||
4820 | struct file *filep, | ||
4821 | int stop_mode, int flags) | ||
4822 | { | ||
4823 | int err = ME_ERRNO_SUCCESS; | ||
4824 | me4600_ao_subdevice_t *instance; | ||
4825 | unsigned long cpu_flags; | ||
4826 | unsigned long tmp; | ||
4827 | |||
4828 | PDEBUG("executed.\n"); | ||
4829 | |||
4830 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
4831 | |||
4832 | if (!instance->fifo) { | ||
4833 | PERROR("Not a streaming ao.\n"); | ||
4834 | return ME_ERRNO_NOT_SUPPORTED; | ||
4835 | } | ||
4836 | |||
4837 | ME_SUBDEVICE_ENTER; | ||
4838 | |||
4839 | if (stop_mode == ME_STOP_MODE_IMMEDIATE) { | ||
4840 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
4841 | tmp = inl(instance->ctrl_reg); | ||
4842 | tmp |= | ||
4843 | ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
4844 | outl(tmp, instance->ctrl_reg); | ||
4845 | |||
4846 | while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ; | ||
4847 | |||
4848 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
4849 | } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { | ||
4850 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
4851 | tmp = inl(instance->ctrl_reg); | ||
4852 | tmp |= ME4600_AO_CTRL_BIT_STOP; | ||
4853 | outl(tmp, instance->ctrl_reg); | ||
4854 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
4855 | } else { | ||
4856 | PERROR("Invalid stop mode specified.\n"); | ||
4857 | err = ME_ERRNO_INVALID_STOP_MODE; | ||
4858 | goto ERROR; | ||
4859 | } | ||
4860 | |||
4861 | ERROR: | ||
4862 | |||
4863 | ME_SUBDEVICE_EXIT; | ||
4864 | |||
4865 | return err; | ||
4866 | } | ||
4867 | |||
4868 | static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, | ||
4869 | struct file *filep, | ||
4870 | int write_mode, | ||
4871 | int *values, int *count, int flags) | ||
4872 | { | ||
4873 | int err = ME_ERRNO_SUCCESS; | ||
4874 | me4600_ao_subdevice_t *instance; | ||
4875 | unsigned long tmp; | ||
4876 | int i; | ||
4877 | int value; | ||
4878 | int cnt = *count; | ||
4879 | int c; | ||
4880 | int k; | ||
4881 | int ret = 0; | ||
4882 | unsigned long cpu_flags = 0; | ||
4883 | |||
4884 | PDEBUG("executed.\n"); | ||
4885 | |||
4886 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
4887 | |||
4888 | if (!instance->fifo) { | ||
4889 | PERROR("Not a streaming ao.\n"); | ||
4890 | return ME_ERRNO_NOT_SUPPORTED; | ||
4891 | } | ||
4892 | |||
4893 | ME_SUBDEVICE_ENTER; | ||
4894 | |||
4895 | if (*count <= 0) { | ||
4896 | PERROR("Invalid count of values specified.\n"); | ||
4897 | err = ME_ERRNO_INVALID_VALUE_COUNT; | ||
4898 | goto ERROR; | ||
4899 | } | ||
4900 | |||
4901 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
4902 | |||
4903 | tmp = inl(instance->ctrl_reg); | ||
4904 | |||
4905 | switch (tmp & 0x3) { | ||
4906 | |||
4907 | case 1: // Wraparound mode | ||
4908 | if (instance->bosch_fw) { // Bosch firmware | ||
4909 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
4910 | cpu_flags); | ||
4911 | |||
4912 | if (cnt != 7) { | ||
4913 | PERROR | ||
4914 | ("Invalid count of values specified. 7 expected.\n"); | ||
4915 | err = ME_ERRNO_INVALID_VALUE_COUNT; | ||
4916 | goto ERROR; | ||
4917 | } | ||
4918 | |||
4919 | for (i = 0; i < 7; i++) { | ||
4920 | if (get_user(value, values)) { | ||
4921 | PERROR | ||
4922 | ("Can't copy value from user space.\n"); | ||
4923 | err = ME_ERRNO_INTERNAL; | ||
4924 | goto ERROR; | ||
4925 | } | ||
4926 | |||
4927 | if (i == 0) { | ||
4928 | /* Maximum voltage */ | ||
4929 | value <<= 16; | ||
4930 | value |= | ||
4931 | inl(instance->reg_base + | ||
4932 | 0xD4) & 0xFFFF; | ||
4933 | outl(value, instance->reg_base + 0xD4); | ||
4934 | } else if (i == 1) { | ||
4935 | /* Minimum voltage */ | ||
4936 | value &= 0xFFFF; | ||
4937 | value |= | ||
4938 | inl(instance->reg_base + | ||
4939 | 0xD4) & 0xFFFF0000; | ||
4940 | outl(value, instance->reg_base + 0xD4); | ||
4941 | } else if (i == 2) { | ||
4942 | /* Delta up */ | ||
4943 | value <<= 16; | ||
4944 | value |= | ||
4945 | inl(instance->reg_base + | ||
4946 | 0xD8) & 0xFFFF; | ||
4947 | outl(value, instance->reg_base + 0xD8); | ||
4948 | } else if (i == 3) { | ||
4949 | /* Delta down */ | ||
4950 | value &= 0xFFFF; | ||
4951 | value |= | ||
4952 | inl(instance->reg_base + | ||
4953 | 0xD8) & 0xFFFF0000; | ||
4954 | outl(value, instance->reg_base + 0xD8); | ||
4955 | } else if (i == 4) { | ||
4956 | /* Start value */ | ||
4957 | outl(value, instance->reg_base + 0xDC); | ||
4958 | } else if (i == 5) { | ||
4959 | /* Invert */ | ||
4960 | if (value) { | ||
4961 | value = inl(instance->ctrl_reg); | ||
4962 | value |= 0x100; | ||
4963 | outl(value, instance->ctrl_reg); | ||
4964 | } else { | ||
4965 | value = inl(instance->ctrl_reg); | ||
4966 | value &= ~0x100; | ||
4967 | outl(value, instance->ctrl_reg); | ||
4968 | } | ||
4969 | } else if (i == 6) { | ||
4970 | /* Timer for positive ramp */ | ||
4971 | outl(value, instance->reg_base + 0xE0); | ||
4972 | } | ||
4973 | |||
4974 | values++; | ||
4975 | } | ||
4976 | } else { // Normal firmware | ||
4977 | PDEBUG("Write for wraparound mode.\n"); | ||
4978 | |||
4979 | if (inl(instance->status_reg) & | ||
4980 | ME4600_AO_STATUS_BIT_FSM) { | ||
4981 | spin_unlock_irqrestore(&instance-> | ||
4982 | subdevice_lock, | ||
4983 | cpu_flags); | ||
4984 | PERROR | ||
4985 | ("There is already a conversion running.\n"); | ||
4986 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
4987 | goto ERROR; | ||
4988 | } | ||
4989 | |||
4990 | tmp |= ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
4991 | tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO; | ||
4992 | outl(tmp, instance->ctrl_reg); | ||
4993 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_FIFO; | ||
4994 | |||
4995 | if ((*count > ME4600_AO_FIFO_COUNT) || | ||
4996 | ((instance-> | ||
4997 | flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == | ||
4998 | ME4600_AO_FLAGS_SW_WRAP_MODE_FIN)) { | ||
4999 | tmp &= | ||
5000 | ~(ME4600_AO_CTRL_BIT_MODE_0 | | ||
5001 | ME4600_AO_CTRL_BIT_MODE_1); | ||
5002 | tmp |= ME4600_AO_CTRL_BIT_MODE_1; | ||
5003 | } | ||
5004 | |||
5005 | outl(tmp, instance->ctrl_reg); | ||
5006 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
5007 | cpu_flags); | ||
5008 | |||
5009 | if ((*count <= ME4600_AO_FIFO_COUNT) && | ||
5010 | ((instance-> | ||
5011 | flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == | ||
5012 | ME4600_AO_FLAGS_SW_WRAP_MODE_INF)) { | ||
5013 | for (i = 0; i < *count; i++) { | ||
5014 | if (get_user(value, values + i)) { | ||
5015 | PERROR | ||
5016 | ("Cannot copy value from user space.\n"); | ||
5017 | err = ME_ERRNO_INTERNAL; | ||
5018 | goto ERROR; | ||
5019 | } | ||
5020 | |||
5021 | if (instance->ao_idx & 0x1) | ||
5022 | value <<= 16; | ||
5023 | |||
5024 | outl(value, instance->fifo_reg); | ||
5025 | } | ||
5026 | } else if ((*count <= ME4600_AO_CIRC_BUF_COUNT) && | ||
5027 | ((instance-> | ||
5028 | flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) | ||
5029 | == ME4600_AO_FLAGS_SW_WRAP_MODE_INF)) { | ||
5030 | for (i = 0; i < *count; i++) { | ||
5031 | if (get_user(value, values + i)) { | ||
5032 | PERROR | ||
5033 | ("Cannot copy value from user space.\n"); | ||
5034 | err = ME_ERRNO_INTERNAL; | ||
5035 | goto ERROR; | ||
5036 | } | ||
5037 | |||
5038 | instance->circ_buf.buf[i] = value; /* Used to hold the values. */ | ||
5039 | } | ||
5040 | |||
5041 | instance->circ_buf.tail = 0; /* Used as the current read position. */ | ||
5042 | instance->circ_buf.head = *count; /* Used as the buffer size. */ | ||
5043 | |||
5044 | /* Preload the FIFO. */ | ||
5045 | |||
5046 | for (i = 0; i < ME4600_AO_FIFO_COUNT; | ||
5047 | i++, instance->circ_buf.tail++) { | ||
5048 | if (instance->circ_buf.tail >= | ||
5049 | instance->circ_buf.head) | ||
5050 | instance->circ_buf.tail = 0; | ||
5051 | |||
5052 | if (instance->ao_idx & 0x1) | ||
5053 | outl(instance->circ_buf. | ||
5054 | buf[instance->circ_buf. | ||
5055 | tail] << 16, | ||
5056 | instance->fifo_reg); | ||
5057 | else | ||
5058 | outl(instance->circ_buf. | ||
5059 | buf[instance->circ_buf. | ||
5060 | tail], | ||
5061 | instance->fifo_reg); | ||
5062 | } | ||
5063 | } else if ((*count <= ME4600_AO_CIRC_BUF_COUNT) && | ||
5064 | ((instance-> | ||
5065 | flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) | ||
5066 | == ME4600_AO_FLAGS_SW_WRAP_MODE_FIN)) { | ||
5067 | unsigned int preload_count; | ||
5068 | |||
5069 | for (i = 0; i < *count; i++) { | ||
5070 | if (get_user(value, values + i)) { | ||
5071 | PERROR | ||
5072 | ("Cannot copy value from user space.\n"); | ||
5073 | err = ME_ERRNO_INTERNAL; | ||
5074 | goto ERROR; | ||
5075 | } | ||
5076 | |||
5077 | instance->circ_buf.buf[i] = value; /* Used to hold the values. */ | ||
5078 | } | ||
5079 | |||
5080 | instance->circ_buf.tail = 0; /* Used as the current read position. */ | ||
5081 | instance->circ_buf.head = *count; /* Used as the buffer size. */ | ||
5082 | |||
5083 | /* Try to preload the whole FIFO. */ | ||
5084 | preload_count = ME4600_AO_FIFO_COUNT; | ||
5085 | |||
5086 | if (preload_count > instance->wrap_count) | ||
5087 | preload_count = instance->wrap_count; | ||
5088 | |||
5089 | /* Preload the FIFO. */ | ||
5090 | for (i = 0; i < preload_count; | ||
5091 | i++, instance->circ_buf.tail++) { | ||
5092 | if (instance->circ_buf.tail >= | ||
5093 | instance->circ_buf.head) | ||
5094 | instance->circ_buf.tail = 0; | ||
5095 | |||
5096 | if (instance->ao_idx & 0x1) | ||
5097 | outl(instance->circ_buf. | ||
5098 | buf[instance->circ_buf. | ||
5099 | tail] << 16, | ||
5100 | instance->fifo_reg); | ||
5101 | else | ||
5102 | outl(instance->circ_buf. | ||
5103 | buf[instance->circ_buf. | ||
5104 | tail], | ||
5105 | instance->fifo_reg); | ||
5106 | } | ||
5107 | |||
5108 | instance->wrap_remaining = | ||
5109 | instance->wrap_count - preload_count; | ||
5110 | } else { | ||
5111 | PERROR("To many values written.\n"); | ||
5112 | err = ME_ERRNO_INVALID_VALUE_COUNT; | ||
5113 | goto ERROR; | ||
5114 | } | ||
5115 | } | ||
5116 | |||
5117 | break; | ||
5118 | |||
5119 | case 2: // Continuous mode | ||
5120 | /* Check if in SW wrapround mode */ | ||
5121 | if (instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) { | ||
5122 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
5123 | cpu_flags); | ||
5124 | PERROR("Subdevice is configured SW wrapround mode.\n"); | ||
5125 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
5126 | goto ERROR; | ||
5127 | } | ||
5128 | |||
5129 | switch (write_mode) { | ||
5130 | |||
5131 | case ME_WRITE_MODE_BLOCKING: | ||
5132 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
5133 | cpu_flags); | ||
5134 | |||
5135 | PDEBUG("Write for blocking continuous mode.\n"); | ||
5136 | |||
5137 | while (cnt > 0) { | ||
5138 | wait_event_interruptible(instance->wait_queue, | ||
5139 | (c = | ||
5140 | me_circ_buf_space_to_end | ||
5141 | (&instance-> | ||
5142 | circ_buf))); | ||
5143 | |||
5144 | if (instance-> | ||
5145 | flags & ME4600_AO_FLAGS_BROKEN_PIPE) { | ||
5146 | PERROR | ||
5147 | ("Broken pipe in blocking write.\n"); | ||
5148 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
5149 | goto ERROR; | ||
5150 | } else if (signal_pending(current)) { | ||
5151 | PERROR | ||
5152 | ("Wait for free buffer interrupted from signal.\n"); | ||
5153 | err = ME_ERRNO_SIGNAL; | ||
5154 | goto ERROR; | ||
5155 | } | ||
5156 | |||
5157 | PDEBUG("Space to end = %d.\n", c); | ||
5158 | |||
5159 | /* Only able to write size of free buffer or size of count */ | ||
5160 | |||
5161 | if (cnt < c) | ||
5162 | c = cnt; | ||
5163 | k = sizeof(int) * c; | ||
5164 | k -= copy_from_user(instance->circ_buf.buf + | ||
5165 | instance->circ_buf.head, | ||
5166 | values, k); | ||
5167 | c = k / sizeof(int); | ||
5168 | |||
5169 | PDEBUG("Copy %d values from user space.\n", c); | ||
5170 | |||
5171 | if (!c) { | ||
5172 | PERROR | ||
5173 | ("Cannot copy values from user space.\n"); | ||
5174 | err = ME_ERRNO_INTERNAL; | ||
5175 | goto ERROR; | ||
5176 | } | ||
5177 | |||
5178 | instance->circ_buf.head = | ||
5179 | (instance->circ_buf.head + | ||
5180 | c) & (instance->circ_buf.mask); | ||
5181 | |||
5182 | values += c; | ||
5183 | cnt -= c; | ||
5184 | ret += c; | ||
5185 | |||
5186 | /* Values are now available so enable interrupts */ | ||
5187 | spin_lock_irqsave(&instance->subdevice_lock, | ||
5188 | cpu_flags); | ||
5189 | |||
5190 | if (me_circ_buf_space(&instance->circ_buf)) { | ||
5191 | tmp = inl(instance->ctrl_reg); | ||
5192 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
5193 | outl(tmp, instance->ctrl_reg); | ||
5194 | } | ||
5195 | |||
5196 | spin_unlock_irqrestore(&instance-> | ||
5197 | subdevice_lock, | ||
5198 | cpu_flags); | ||
5199 | } | ||
5200 | |||
5201 | *count = ret; | ||
5202 | |||
5203 | break; | ||
5204 | |||
5205 | case ME_WRITE_MODE_NONBLOCKING: | ||
5206 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
5207 | cpu_flags); | ||
5208 | |||
5209 | PDEBUG("Write for non blocking continuous mode.\n"); | ||
5210 | |||
5211 | while (cnt > 0) { | ||
5212 | if (instance-> | ||
5213 | flags & ME4600_AO_FLAGS_BROKEN_PIPE) { | ||
5214 | PERROR | ||
5215 | ("ME4600:Broken pipe in nonblocking write.\n"); | ||
5216 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
5217 | goto ERROR; | ||
5218 | } | ||
5219 | |||
5220 | c = me_circ_buf_space_to_end(&instance-> | ||
5221 | circ_buf); | ||
5222 | |||
5223 | if (!c) { | ||
5224 | PDEBUG | ||
5225 | ("Returning from nonblocking write.\n"); | ||
5226 | break; | ||
5227 | } | ||
5228 | |||
5229 | PDEBUG("Space to end = %d.\n", c); | ||
5230 | |||
5231 | /* Only able to write size of free buffer or size of count */ | ||
5232 | |||
5233 | if (cnt < c) | ||
5234 | c = cnt; | ||
5235 | k = sizeof(int) * c; | ||
5236 | k -= copy_from_user(instance->circ_buf.buf + | ||
5237 | instance->circ_buf.head, | ||
5238 | values, k); | ||
5239 | c = k / sizeof(int); | ||
5240 | |||
5241 | PDEBUG("Copy %d values from user space.\n", c); | ||
5242 | |||
5243 | if (!c) { | ||
5244 | PERROR | ||
5245 | ("Cannot copy values from user space.\n"); | ||
5246 | err = ME_ERRNO_INTERNAL; | ||
5247 | goto ERROR; | ||
5248 | } | ||
5249 | |||
5250 | instance->circ_buf.head = | ||
5251 | (instance->circ_buf.head + | ||
5252 | c) & (instance->circ_buf.mask); | ||
5253 | |||
5254 | values += c; | ||
5255 | cnt -= c; | ||
5256 | ret += c; | ||
5257 | |||
5258 | /* Values are now available so enable interrupts */ | ||
5259 | spin_lock_irqsave(&instance->subdevice_lock, | ||
5260 | cpu_flags); | ||
5261 | |||
5262 | if (me_circ_buf_space(&instance->circ_buf)) { | ||
5263 | tmp = inl(instance->ctrl_reg); | ||
5264 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
5265 | outl(tmp, instance->ctrl_reg); | ||
5266 | } | ||
5267 | |||
5268 | spin_unlock_irqrestore(&instance-> | ||
5269 | subdevice_lock, | ||
5270 | cpu_flags); | ||
5271 | } | ||
5272 | |||
5273 | *count = ret; | ||
5274 | |||
5275 | break; | ||
5276 | |||
5277 | case ME_WRITE_MODE_PRELOAD: | ||
5278 | PDEBUG("Write for preload continuous mode.\n"); | ||
5279 | |||
5280 | if ((inl(instance->status_reg) & | ||
5281 | ME4600_AO_STATUS_BIT_FSM)) { | ||
5282 | spin_unlock_irqrestore(&instance-> | ||
5283 | subdevice_lock, | ||
5284 | cpu_flags); | ||
5285 | PERROR | ||
5286 | ("Can't Preload DAC FIFO while conversion is running.\n"); | ||
5287 | err = ME_ERRNO_SUBDEVICE_BUSY; | ||
5288 | goto ERROR; | ||
5289 | } | ||
5290 | |||
5291 | tmp = inl(instance->ctrl_reg); | ||
5292 | |||
5293 | tmp |= | ||
5294 | ME4600_AO_CTRL_BIT_STOP | | ||
5295 | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
5296 | outl(tmp, instance->ctrl_reg); | ||
5297 | tmp &= | ||
5298 | ~(ME4600_AO_CTRL_BIT_ENABLE_FIFO | | ||
5299 | ME4600_AO_CTRL_BIT_ENABLE_IRQ); | ||
5300 | outl(tmp, instance->ctrl_reg); | ||
5301 | tmp |= ME4600_AO_CTRL_BIT_ENABLE_FIFO; | ||
5302 | outl(tmp, instance->ctrl_reg); | ||
5303 | |||
5304 | instance->circ_buf.head = 0; | ||
5305 | instance->circ_buf.tail = 0; | ||
5306 | instance->flags &= ~ME4600_AO_FLAGS_BROKEN_PIPE; | ||
5307 | |||
5308 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
5309 | cpu_flags); | ||
5310 | |||
5311 | c = ME4600_AO_FIFO_COUNT; | ||
5312 | |||
5313 | if (cnt < c) | ||
5314 | c = cnt; | ||
5315 | |||
5316 | for (i = 0; i < c; i++) { | ||
5317 | if (get_user(value, values)) { | ||
5318 | PERROR | ||
5319 | ("Can't copy value from user space.\n"); | ||
5320 | err = ME_ERRNO_INTERNAL; | ||
5321 | goto ERROR; | ||
5322 | } | ||
5323 | |||
5324 | if (instance->ao_idx & 0x1) | ||
5325 | value <<= 16; | ||
5326 | |||
5327 | outl(value, instance->fifo_reg); | ||
5328 | |||
5329 | values++; | ||
5330 | } | ||
5331 | |||
5332 | cnt -= c; | ||
5333 | |||
5334 | ret += c; | ||
5335 | |||
5336 | PDEBUG("Wrote %d values to fifo.\n", c); | ||
5337 | |||
5338 | while (1) { | ||
5339 | c = me_circ_buf_space_to_end(&instance-> | ||
5340 | circ_buf); | ||
5341 | |||
5342 | if (c == 0) | ||
5343 | break; | ||
5344 | |||
5345 | if (cnt < c) | ||
5346 | c = cnt; | ||
5347 | |||
5348 | if (c <= 0) | ||
5349 | break; | ||
5350 | |||
5351 | k = sizeof(int) * c; | ||
5352 | |||
5353 | k -= copy_from_user(instance->circ_buf.buf + | ||
5354 | instance->circ_buf.head, | ||
5355 | values, k); | ||
5356 | |||
5357 | c = k / sizeof(int); | ||
5358 | |||
5359 | PDEBUG("Wrote %d values to circular buffer.\n", | ||
5360 | c); | ||
5361 | |||
5362 | if (!c) { | ||
5363 | PERROR | ||
5364 | ("Can't copy values from user space.\n"); | ||
5365 | err = ME_ERRNO_INTERNAL; | ||
5366 | goto ERROR; | ||
5367 | } | ||
5368 | |||
5369 | instance->circ_buf.head = | ||
5370 | (instance->circ_buf.head + | ||
5371 | c) & (instance->circ_buf.mask); | ||
5372 | |||
5373 | values += c; | ||
5374 | cnt -= c; | ||
5375 | ret += c; | ||
5376 | } | ||
5377 | |||
5378 | *count = ret; | ||
5379 | |||
5380 | break; | ||
5381 | |||
5382 | default: | ||
5383 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
5384 | cpu_flags); | ||
5385 | |||
5386 | PERROR("Invalid write mode specified.\n"); | ||
5387 | |||
5388 | err = ME_ERRNO_INVALID_WRITE_MODE; | ||
5389 | |||
5390 | goto ERROR; | ||
5391 | } | ||
5392 | |||
5393 | break; | ||
5394 | |||
5395 | default: // Single mode of invalid | ||
5396 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
5397 | PERROR("Subdevice is configured in single mode.\n"); | ||
5398 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
5399 | goto ERROR; | ||
5400 | } | ||
5401 | |||
5402 | ERROR: | ||
5403 | |||
5404 | ME_SUBDEVICE_EXIT; | ||
5405 | |||
5406 | return err; | ||
5407 | } | ||
5408 | |||
5409 | static irqreturn_t me4600_ao_isr(int irq, void *dev_id) | ||
5410 | { | ||
5411 | unsigned long tmp; | ||
5412 | int value; | ||
5413 | me4600_ao_subdevice_t *instance = dev_id; | ||
5414 | int i; | ||
5415 | int c = 0; | ||
5416 | int c1 = 0; | ||
5417 | |||
5418 | if (irq != instance->irq) { | ||
5419 | PDEBUG("Incorrect interrupt num: %d.\n", irq); | ||
5420 | return IRQ_NONE; | ||
5421 | } | ||
5422 | |||
5423 | if (!((0x1 << (instance->ao_idx + 3)) & inl(instance->irq_status_reg))) { | ||
5424 | return IRQ_NONE; | ||
5425 | } | ||
5426 | |||
5427 | PDEBUG("executed.\n"); | ||
5428 | |||
5429 | tmp = inl(instance->status_reg); | ||
5430 | |||
5431 | if (!(tmp & ME4600_AO_STATUS_BIT_EF) && | ||
5432 | (tmp & ME4600_AO_STATUS_BIT_HF) && | ||
5433 | (tmp & ME4600_AO_STATUS_BIT_HF)) { | ||
5434 | c = ME4600_AO_FIFO_COUNT; | ||
5435 | PDEBUG("Fifo empty.\n"); | ||
5436 | } else if ((tmp & ME4600_AO_STATUS_BIT_EF) && | ||
5437 | (tmp & ME4600_AO_STATUS_BIT_HF) && | ||
5438 | (tmp & ME4600_AO_STATUS_BIT_HF)) { | ||
5439 | c = ME4600_AO_FIFO_COUNT / 2; | ||
5440 | PDEBUG("Fifo under half full.\n"); | ||
5441 | } else { | ||
5442 | c = 0; | ||
5443 | PDEBUG("Fifo full.\n"); | ||
5444 | } | ||
5445 | |||
5446 | PDEBUG("Try to write 0x%04X values.\n", c); | ||
5447 | |||
5448 | if ((instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == | ||
5449 | ME4600_AO_FLAGS_SW_WRAP_MODE_INF) { | ||
5450 | while (c) { | ||
5451 | c1 = c; | ||
5452 | |||
5453 | if (c1 > (instance->circ_buf.head - instance->circ_buf.tail)) /* Only up to the end of the buffer */ | ||
5454 | c1 = (instance->circ_buf.head - | ||
5455 | instance->circ_buf.tail); | ||
5456 | |||
5457 | /* Write the values to the FIFO */ | ||
5458 | for (i = 0; i < c1; i++, instance->circ_buf.tail++, c--) { | ||
5459 | if (instance->ao_idx & 0x1) | ||
5460 | outl(instance->circ_buf. | ||
5461 | buf[instance->circ_buf.tail] << 16, | ||
5462 | instance->fifo_reg); | ||
5463 | else | ||
5464 | outl(instance->circ_buf. | ||
5465 | buf[instance->circ_buf.tail], | ||
5466 | instance->fifo_reg); | ||
5467 | } | ||
5468 | |||
5469 | if (instance->circ_buf.tail >= instance->circ_buf.head) /* Start from beginning */ | ||
5470 | instance->circ_buf.tail = 0; | ||
5471 | } | ||
5472 | |||
5473 | spin_lock(&instance->subdevice_lock); | ||
5474 | |||
5475 | tmp = inl(instance->ctrl_reg); | ||
5476 | tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
5477 | outl(tmp, instance->ctrl_reg); | ||
5478 | tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
5479 | outl(tmp, instance->ctrl_reg); | ||
5480 | |||
5481 | if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { | ||
5482 | PERROR("Broken pipe.\n"); | ||
5483 | instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE; | ||
5484 | tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
5485 | outl(tmp, instance->ctrl_reg); | ||
5486 | } | ||
5487 | |||
5488 | spin_unlock(&instance->subdevice_lock); | ||
5489 | } else if ((instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == | ||
5490 | ME4600_AO_FLAGS_SW_WRAP_MODE_FIN) { | ||
5491 | while (c && instance->wrap_remaining) { | ||
5492 | c1 = c; | ||
5493 | |||
5494 | if (c1 > (instance->circ_buf.head - instance->circ_buf.tail)) /* Only up to the end of the buffer */ | ||
5495 | c1 = (instance->circ_buf.head - | ||
5496 | instance->circ_buf.tail); | ||
5497 | |||
5498 | if (c1 > instance->wrap_remaining) /* Only up to count of user defined number of values */ | ||
5499 | c1 = instance->wrap_remaining; | ||
5500 | |||
5501 | /* Write the values to the FIFO */ | ||
5502 | for (i = 0; i < c1; | ||
5503 | i++, instance->circ_buf.tail++, c--, | ||
5504 | instance->wrap_remaining--) { | ||
5505 | if (instance->ao_idx & 0x1) | ||
5506 | outl(instance->circ_buf. | ||
5507 | buf[instance->circ_buf.tail] << 16, | ||
5508 | instance->fifo_reg); | ||
5509 | else | ||
5510 | outl(instance->circ_buf. | ||
5511 | buf[instance->circ_buf.tail], | ||
5512 | instance->fifo_reg); | ||
5513 | } | ||
5514 | |||
5515 | if (instance->circ_buf.tail >= instance->circ_buf.head) /* Start from beginning */ | ||
5516 | instance->circ_buf.tail = 0; | ||
5517 | } | ||
5518 | |||
5519 | spin_lock(&instance->subdevice_lock); | ||
5520 | |||
5521 | tmp = inl(instance->ctrl_reg); | ||
5522 | |||
5523 | if (!instance->wrap_remaining) { | ||
5524 | PDEBUG("Finite SW wraparound done.\n"); | ||
5525 | tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
5526 | } | ||
5527 | |||
5528 | tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
5529 | |||
5530 | outl(tmp, instance->ctrl_reg); | ||
5531 | tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
5532 | outl(tmp, instance->ctrl_reg); | ||
5533 | |||
5534 | if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { | ||
5535 | PERROR("Broken pipe.\n"); | ||
5536 | instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE; | ||
5537 | tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
5538 | outl(tmp, instance->ctrl_reg); | ||
5539 | } | ||
5540 | |||
5541 | spin_unlock(&instance->subdevice_lock); | ||
5542 | |||
5543 | } else { /* Regular continuous mode */ | ||
5544 | |||
5545 | while (1) { | ||
5546 | c1 = me_circ_buf_values_to_end(&instance->circ_buf); | ||
5547 | PDEBUG("Values to end = %d.\n", c1); | ||
5548 | |||
5549 | if (c1 > c) | ||
5550 | c1 = c; | ||
5551 | |||
5552 | if (c1 <= 0) { | ||
5553 | PDEBUG("Work done or buffer empty.\n"); | ||
5554 | break; | ||
5555 | } | ||
5556 | |||
5557 | if (instance->ao_idx & 0x1) { | ||
5558 | for (i = 0; i < c1; i++) { | ||
5559 | value = | ||
5560 | *(instance->circ_buf.buf + | ||
5561 | instance->circ_buf.tail + | ||
5562 | i) << 16; | ||
5563 | outl(value, instance->fifo_reg); | ||
5564 | } | ||
5565 | } else | ||
5566 | outsl(instance->fifo_reg, | ||
5567 | instance->circ_buf.buf + | ||
5568 | instance->circ_buf.tail, c1); | ||
5569 | |||
5570 | instance->circ_buf.tail = | ||
5571 | (instance->circ_buf.tail + | ||
5572 | c1) & (instance->circ_buf.mask); | ||
5573 | |||
5574 | PDEBUG("%d values wrote to port 0x%04X.\n", c1, | ||
5575 | instance->fifo_reg); | ||
5576 | |||
5577 | c -= c1; | ||
5578 | } | ||
5579 | |||
5580 | spin_lock(&instance->subdevice_lock); | ||
5581 | |||
5582 | tmp = inl(instance->ctrl_reg); | ||
5583 | |||
5584 | if (!me_circ_buf_values(&instance->circ_buf)) { | ||
5585 | PDEBUG | ||
5586 | ("Disable Interrupt because no values left in buffer.\n"); | ||
5587 | tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
5588 | } | ||
5589 | |||
5590 | tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
5591 | |||
5592 | outl(tmp, instance->ctrl_reg); | ||
5593 | tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; | ||
5594 | outl(tmp, instance->ctrl_reg); | ||
5595 | |||
5596 | if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { | ||
5597 | PDEBUG("Broken pipe in me4600_ao_isr.\n"); | ||
5598 | instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE; | ||
5599 | tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; | ||
5600 | outl(tmp, instance->ctrl_reg); | ||
5601 | } | ||
5602 | |||
5603 | spin_unlock(&instance->subdevice_lock); | ||
5604 | |||
5605 | wake_up_interruptible(&instance->wait_queue); | ||
5606 | } | ||
5607 | |||
5608 | return IRQ_HANDLED; | ||
5609 | } | ||
5610 | |||
5611 | static void me4600_ao_destructor(struct me_subdevice *subdevice) | ||
5612 | { | ||
5613 | me4600_ao_subdevice_t *instance; | ||
5614 | |||
5615 | PDEBUG("executed.\n"); | ||
5616 | |||
5617 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5618 | |||
5619 | free_irq(instance->irq, instance); | ||
5620 | kfree(instance->circ_buf.buf); | ||
5621 | me_subdevice_deinit(&instance->base); | ||
5622 | kfree(instance); | ||
5623 | } | ||
5624 | |||
5625 | me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, | ||
5626 | spinlock_t *preload_reg_lock, | ||
5627 | uint32_t *preload_flags, | ||
5628 | int ao_idx, int fifo, int irq) | ||
5629 | { | ||
5630 | me4600_ao_subdevice_t *subdevice; | ||
5631 | int err; | ||
5632 | |||
5633 | PDEBUG("executed.\n"); | ||
5634 | |||
5635 | /* Allocate memory for subdevice instance */ | ||
5636 | subdevice = kmalloc(sizeof(me4600_ao_subdevice_t), GFP_KERNEL); | ||
5637 | |||
5638 | if (!subdevice) { | ||
5639 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
5640 | return NULL; | ||
5641 | } | ||
5642 | |||
5643 | memset(subdevice, 0, sizeof(me4600_ao_subdevice_t)); | ||
5644 | |||
5645 | /* Initialize subdevice base class */ | ||
5646 | err = me_subdevice_init(&subdevice->base); | ||
5647 | |||
5648 | if (err) { | ||
5649 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
5650 | kfree(subdevice); | ||
5651 | return NULL; | ||
5652 | } | ||
5653 | // Initialize spin locks. | ||
5654 | spin_lock_init(&subdevice->subdevice_lock); | ||
5655 | |||
5656 | subdevice->preload_reg_lock = preload_reg_lock; | ||
5657 | subdevice->preload_flags = preload_flags; | ||
5658 | |||
5659 | /* Allocate and initialize circular buffer */ | ||
5660 | subdevice->circ_buf.mask = ME4600_AO_CIRC_BUF_COUNT - 1; | ||
5661 | subdevice->circ_buf.buf = kmalloc(ME4600_AO_CIRC_BUF_SIZE, GFP_KERNEL); | ||
5662 | |||
5663 | if (!subdevice->circ_buf.buf) { | ||
5664 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
5665 | me_subdevice_deinit((me_subdevice_t *) subdevice); | ||
5666 | kfree(subdevice); | ||
5667 | return NULL; | ||
5668 | } | ||
5669 | |||
5670 | memset(subdevice->circ_buf.buf, 0, ME4600_AO_CIRC_BUF_SIZE); | ||
5671 | |||
5672 | subdevice->circ_buf.head = 0; | ||
5673 | subdevice->circ_buf.tail = 0; | ||
5674 | |||
5675 | /* Initialize wait queue */ | ||
5676 | init_waitqueue_head(&subdevice->wait_queue); | ||
5677 | |||
5678 | /* Initialize single value to 0V */ | ||
5679 | subdevice->single_value = 0x8000; | ||
5680 | |||
5681 | /* Store analog output index */ | ||
5682 | subdevice->ao_idx = ao_idx; | ||
5683 | |||
5684 | /* Store if analog output has fifo */ | ||
5685 | subdevice->fifo = fifo; | ||
5686 | |||
5687 | /* Initialize registers */ | ||
5688 | |||
5689 | if (ao_idx == 0) { | ||
5690 | subdevice->ctrl_reg = reg_base + ME4600_AO_00_CTRL_REG; | ||
5691 | subdevice->status_reg = reg_base + ME4600_AO_00_STATUS_REG; | ||
5692 | subdevice->fifo_reg = reg_base + ME4600_AO_00_FIFO_REG; | ||
5693 | subdevice->single_reg = reg_base + ME4600_AO_00_SINGLE_REG; | ||
5694 | subdevice->timer_reg = reg_base + ME4600_AO_00_TIMER_REG; | ||
5695 | subdevice->reg_base = reg_base; | ||
5696 | |||
5697 | if (inl(subdevice->reg_base + ME4600_AO_BOSCH_REG) == 0x20000) { | ||
5698 | PINFO("Bosch firmware in use for channel 0.\n"); | ||
5699 | subdevice->bosch_fw = 1; | ||
5700 | } else { | ||
5701 | subdevice->bosch_fw = 0; | ||
5702 | } | ||
5703 | } else if (ao_idx == 1) { | ||
5704 | subdevice->ctrl_reg = reg_base + ME4600_AO_01_CTRL_REG; | ||
5705 | subdevice->status_reg = reg_base + ME4600_AO_01_STATUS_REG; | ||
5706 | subdevice->fifo_reg = reg_base + ME4600_AO_01_FIFO_REG; | ||
5707 | subdevice->single_reg = reg_base + ME4600_AO_01_SINGLE_REG; | ||
5708 | subdevice->timer_reg = reg_base + ME4600_AO_01_TIMER_REG; | ||
5709 | subdevice->reg_base = reg_base; | ||
5710 | subdevice->bosch_fw = 0; | ||
5711 | } else if (ao_idx == 2) { | ||
5712 | subdevice->ctrl_reg = reg_base + ME4600_AO_02_CTRL_REG; | ||
5713 | subdevice->status_reg = reg_base + ME4600_AO_02_STATUS_REG; | ||
5714 | subdevice->fifo_reg = reg_base + ME4600_AO_02_FIFO_REG; | ||
5715 | subdevice->single_reg = reg_base + ME4600_AO_02_SINGLE_REG; | ||
5716 | subdevice->timer_reg = reg_base + ME4600_AO_02_TIMER_REG; | ||
5717 | subdevice->reg_base = reg_base; | ||
5718 | subdevice->bosch_fw = 0; | ||
5719 | } else { | ||
5720 | subdevice->ctrl_reg = reg_base + ME4600_AO_03_CTRL_REG; | ||
5721 | subdevice->status_reg = reg_base + ME4600_AO_03_STATUS_REG; | ||
5722 | subdevice->fifo_reg = reg_base + ME4600_AO_03_FIFO_REG; | ||
5723 | subdevice->single_reg = reg_base + ME4600_AO_03_SINGLE_REG; | ||
5724 | subdevice->timer_reg = reg_base + ME4600_AO_03_TIMER_REG; | ||
5725 | subdevice->reg_base = reg_base; | ||
5726 | subdevice->bosch_fw = 0; | ||
5727 | } | ||
5728 | |||
5729 | subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; | ||
5730 | subdevice->preload_reg = reg_base + ME4600_AO_LOADSETREG_XX; | ||
5731 | |||
5732 | /* Register interrupt service routine */ | ||
5733 | subdevice->irq = irq; | ||
5734 | |||
5735 | if (request_irq | ||
5736 | (subdevice->irq, me4600_ao_isr, IRQF_DISABLED | IRQF_SHARED, | ||
5737 | ME4600_NAME, subdevice)) { | ||
5738 | PERROR("Cannot get interrupt line.\n"); | ||
5739 | me_subdevice_deinit((me_subdevice_t *) subdevice); | ||
5740 | kfree(subdevice->circ_buf.buf); | ||
5741 | kfree(subdevice); | ||
5742 | return NULL; | ||
5743 | } | ||
5744 | |||
5745 | /* Override base class methods. */ | ||
5746 | subdevice->base.me_subdevice_destructor = me4600_ao_destructor; | ||
5747 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
5748 | me4600_ao_io_reset_subdevice; | ||
5749 | subdevice->base.me_subdevice_io_single_config = | ||
5750 | me4600_ao_io_single_config; | ||
5751 | subdevice->base.me_subdevice_io_single_read = me4600_ao_io_single_read; | ||
5752 | subdevice->base.me_subdevice_io_single_write = | ||
5753 | me4600_ao_io_single_write; | ||
5754 | subdevice->base.me_subdevice_io_stream_config = | ||
5755 | me4600_ao_io_stream_config; | ||
5756 | subdevice->base.me_subdevice_io_stream_new_values = | ||
5757 | me4600_ao_io_stream_new_values; | ||
5758 | subdevice->base.me_subdevice_io_stream_write = | ||
5759 | me4600_ao_io_stream_write; | ||
5760 | subdevice->base.me_subdevice_io_stream_start = | ||
5761 | me4600_ao_io_stream_start; | ||
5762 | subdevice->base.me_subdevice_io_stream_status = | ||
5763 | me4600_ao_io_stream_status; | ||
5764 | subdevice->base.me_subdevice_io_stream_stop = me4600_ao_io_stream_stop; | ||
5765 | subdevice->base.me_subdevice_query_number_channels = | ||
5766 | me4600_ao_query_number_channels; | ||
5767 | subdevice->base.me_subdevice_query_subdevice_type = | ||
5768 | me4600_ao_query_subdevice_type; | ||
5769 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
5770 | me4600_ao_query_subdevice_caps; | ||
5771 | subdevice->base.me_subdevice_query_subdevice_caps_args = | ||
5772 | me4600_ao_query_subdevice_caps_args; | ||
5773 | subdevice->base.me_subdevice_query_range_by_min_max = | ||
5774 | me4600_ao_query_range_by_min_max; | ||
5775 | subdevice->base.me_subdevice_query_number_ranges = | ||
5776 | me4600_ao_query_number_ranges; | ||
5777 | subdevice->base.me_subdevice_query_range_info = | ||
5778 | me4600_ao_query_range_info; | ||
5779 | subdevice->base.me_subdevice_query_timer = me4600_ao_query_timer; | ||
5780 | |||
5781 | return subdevice; | ||
5782 | } | ||
5783 | |||
5784 | #endif // BOSCH | ||
5785 | |||
5786 | /* Common functions | ||
5787 | */ | ||
5788 | |||
5789 | static int me4600_ao_query_range_by_min_max(me_subdevice_t *subdevice, | ||
5790 | int unit, | ||
5791 | int *min, | ||
5792 | int *max, int *maxdata, int *range) | ||
5793 | { | ||
5794 | me4600_ao_subdevice_t *instance; | ||
5795 | |||
5796 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5797 | |||
5798 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5799 | |||
5800 | if ((*max - *min) < 0) { | ||
5801 | PERROR("Invalid minimum and maximum values specified.\n"); | ||
5802 | return ME_ERRNO_INVALID_MIN_MAX; | ||
5803 | } | ||
5804 | |||
5805 | if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { | ||
5806 | if ((*max <= (ME4600_AO_MAX_RANGE + 1000)) | ||
5807 | && (*min >= ME4600_AO_MIN_RANGE)) { | ||
5808 | *min = ME4600_AO_MIN_RANGE; | ||
5809 | *max = ME4600_AO_MAX_RANGE; | ||
5810 | *maxdata = ME4600_AO_MAX_DATA; | ||
5811 | *range = 0; | ||
5812 | } else { | ||
5813 | PERROR("No matching range available.\n"); | ||
5814 | return ME_ERRNO_NO_RANGE; | ||
5815 | } | ||
5816 | } else { | ||
5817 | PERROR("Invalid physical unit specified.\n"); | ||
5818 | return ME_ERRNO_INVALID_UNIT; | ||
5819 | } | ||
5820 | |||
5821 | return ME_ERRNO_SUCCESS; | ||
5822 | } | ||
5823 | |||
5824 | static int me4600_ao_query_number_ranges(me_subdevice_t *subdevice, | ||
5825 | int unit, int *count) | ||
5826 | { | ||
5827 | me4600_ao_subdevice_t *instance; | ||
5828 | |||
5829 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5830 | |||
5831 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5832 | |||
5833 | if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { | ||
5834 | *count = 1; | ||
5835 | } else { | ||
5836 | *count = 0; | ||
5837 | } | ||
5838 | |||
5839 | return ME_ERRNO_SUCCESS; | ||
5840 | } | ||
5841 | |||
5842 | static int me4600_ao_query_range_info(me_subdevice_t *subdevice, | ||
5843 | int range, | ||
5844 | int *unit, | ||
5845 | int *min, int *max, int *maxdata) | ||
5846 | { | ||
5847 | me4600_ao_subdevice_t *instance; | ||
5848 | |||
5849 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5850 | |||
5851 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5852 | |||
5853 | if (range == 0) { | ||
5854 | *unit = ME_UNIT_VOLT; | ||
5855 | *min = ME4600_AO_MIN_RANGE; | ||
5856 | *max = ME4600_AO_MAX_RANGE; | ||
5857 | *maxdata = ME4600_AO_MAX_DATA; | ||
5858 | } else { | ||
5859 | PERROR("Invalid range number specified.\n"); | ||
5860 | return ME_ERRNO_INVALID_RANGE; | ||
5861 | } | ||
5862 | |||
5863 | return ME_ERRNO_SUCCESS; | ||
5864 | } | ||
5865 | |||
5866 | static int me4600_ao_query_timer(me_subdevice_t *subdevice, | ||
5867 | int timer, | ||
5868 | int *base_frequency, | ||
5869 | long long *min_ticks, long long *max_ticks) | ||
5870 | { | ||
5871 | me4600_ao_subdevice_t *instance; | ||
5872 | |||
5873 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5874 | |||
5875 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5876 | |||
5877 | if ((timer != ME_TIMER_ACQ_START) && (timer != ME_TIMER_CONV_START)) { | ||
5878 | PERROR("Invalid timer specified.\n"); | ||
5879 | return ME_ERRNO_INVALID_TIMER; | ||
5880 | } | ||
5881 | |||
5882 | if (instance->fifo) { //Streaming device. | ||
5883 | *base_frequency = ME4600_AO_BASE_FREQUENCY; | ||
5884 | if (timer == ME_TIMER_ACQ_START) { | ||
5885 | *min_ticks = ME4600_AO_MIN_ACQ_TICKS; | ||
5886 | *max_ticks = ME4600_AO_MAX_ACQ_TICKS; | ||
5887 | } else if (timer == ME_TIMER_CONV_START) { | ||
5888 | *min_ticks = ME4600_AO_MIN_CHAN_TICKS; | ||
5889 | *max_ticks = ME4600_AO_MAX_CHAN_TICKS; | ||
5890 | } | ||
5891 | } else { //Not streaming device! | ||
5892 | *base_frequency = 0; | ||
5893 | *min_ticks = 0; | ||
5894 | *max_ticks = 0; | ||
5895 | } | ||
5896 | |||
5897 | return ME_ERRNO_SUCCESS; | ||
5898 | } | ||
5899 | |||
5900 | static int me4600_ao_query_number_channels(me_subdevice_t *subdevice, | ||
5901 | int *number) | ||
5902 | { | ||
5903 | me4600_ao_subdevice_t *instance; | ||
5904 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5905 | |||
5906 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5907 | |||
5908 | *number = 1; | ||
5909 | |||
5910 | return ME_ERRNO_SUCCESS; | ||
5911 | } | ||
5912 | |||
5913 | static int me4600_ao_query_subdevice_type(me_subdevice_t *subdevice, | ||
5914 | int *type, int *subtype) | ||
5915 | { | ||
5916 | me4600_ao_subdevice_t *instance; | ||
5917 | |||
5918 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5919 | |||
5920 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5921 | |||
5922 | *type = ME_TYPE_AO; | ||
5923 | *subtype = (instance->fifo) ? ME_SUBTYPE_STREAMING : ME_SUBTYPE_SINGLE; | ||
5924 | |||
5925 | return ME_ERRNO_SUCCESS; | ||
5926 | } | ||
5927 | |||
5928 | static int me4600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
5929 | { | ||
5930 | me4600_ao_subdevice_t *instance; | ||
5931 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5932 | |||
5933 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5934 | |||
5935 | *caps = | ||
5936 | ME_CAPS_AO_TRIG_SYNCHRONOUS | ((instance->fifo) ? ME_CAPS_AO_FIFO : | ||
5937 | ME_CAPS_NONE); | ||
5938 | |||
5939 | return ME_ERRNO_SUCCESS; | ||
5940 | } | ||
5941 | |||
5942 | static int me4600_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, | ||
5943 | int cap, int *args, int count) | ||
5944 | { | ||
5945 | me4600_ao_subdevice_t *instance; | ||
5946 | int err = ME_ERRNO_SUCCESS; | ||
5947 | |||
5948 | instance = (me4600_ao_subdevice_t *) subdevice; | ||
5949 | |||
5950 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
5951 | |||
5952 | if (count != 1) { | ||
5953 | PERROR("Invalid capability argument count.\n"); | ||
5954 | return ME_ERRNO_INVALID_CAP_ARG_COUNT; | ||
5955 | } | ||
5956 | |||
5957 | switch (cap) { | ||
5958 | case ME_CAP_AI_FIFO_SIZE: | ||
5959 | args[0] = (instance->fifo) ? ME4600_AO_FIFO_COUNT : 0; | ||
5960 | break; | ||
5961 | |||
5962 | case ME_CAP_AI_BUFFER_SIZE: | ||
5963 | args[0] = | ||
5964 | (instance->circ_buf.buf) ? ME4600_AO_CIRC_BUF_COUNT : 0; | ||
5965 | break; | ||
5966 | |||
5967 | default: | ||
5968 | PERROR("Invalid capability.\n"); | ||
5969 | err = ME_ERRNO_INVALID_CAP; | ||
5970 | args[0] = 0; | ||
5971 | } | ||
5972 | |||
5973 | return err; | ||
5974 | } | ||
diff --git a/drivers/staging/meilhaus/me4600_ao.h b/drivers/staging/meilhaus/me4600_ao.h deleted file mode 100644 index 7579435adc67..000000000000 --- a/drivers/staging/meilhaus/me4600_ao.h +++ /dev/null | |||
@@ -1,259 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ao.h | ||
3 | * | ||
4 | * @brief Meilhaus ME-4000 analog output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_AO_H_ | ||
28 | # define _ME4600_AO_H_ | ||
29 | |||
30 | # include <linux/version.h> | ||
31 | # include "mesubdevice.h" | ||
32 | # include "mecirc_buf.h" | ||
33 | # include "meioctl.h" | ||
34 | |||
35 | # ifdef __KERNEL__ | ||
36 | |||
37 | # ifdef BOSCH | ||
38 | # undef ME_SYNAPSE | ||
39 | # ifndef _CBUFF_32b_t | ||
40 | # define _CBUFF_32b_t | ||
41 | # endif //_CBUFF_32b_t | ||
42 | # endif //BOSCH | ||
43 | |||
44 | # define ME4600_AO_MAX_SUBDEVICES 4 | ||
45 | # define ME4600_AO_FIFO_COUNT 4096 | ||
46 | |||
47 | # define ME4600_AO_BASE_FREQUENCY 33000000LL | ||
48 | |||
49 | # define ME4600_AO_MIN_ACQ_TICKS 0LL | ||
50 | # define ME4600_AO_MAX_ACQ_TICKS 0LL | ||
51 | |||
52 | # define ME4600_AO_MIN_CHAN_TICKS 66LL | ||
53 | # define ME4600_AO_MAX_CHAN_TICKS 0xFFFFFFFFLL | ||
54 | |||
55 | # define ME4600_AO_MIN_RANGE -10000000 | ||
56 | # define ME4600_AO_MAX_RANGE 9999694 | ||
57 | |||
58 | # define ME4600_AO_MAX_DATA 0xFFFF | ||
59 | |||
60 | # ifdef ME_SYNAPSE | ||
61 | # define ME4600_AO_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse | ||
62 | # else | ||
63 | # define ME4600_AO_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB | ||
64 | # endif | ||
65 | # define ME4600_AO_CIRC_BUF_SIZE PAGE_SIZE<<ME4600_AO_CIRC_BUF_SIZE_ORDER // Buffer size in bytes. | ||
66 | |||
67 | # ifdef _CBUFF_32b_t | ||
68 | # define ME4600_AO_CIRC_BUF_COUNT ((ME4600_AO_CIRC_BUF_SIZE) / sizeof(uint32_t)) // Size in values | ||
69 | # else | ||
70 | # define ME4600_AO_CIRC_BUF_COUNT ((ME4600_AO_CIRC_BUF_SIZE) / sizeof(uint16_t)) // Size in values | ||
71 | # endif | ||
72 | |||
73 | # define ME4600_AO_CONTINOUS 0x0 | ||
74 | # define ME4600_AO_WRAP_MODE 0x1 | ||
75 | # define ME4600_AO_HW_MODE 0x2 | ||
76 | |||
77 | # define ME4600_AO_HW_WRAP_MODE (ME4600_AO_WRAP_MODE | ME4600_AO_HW_MODE) | ||
78 | # define ME4600_AO_SW_WRAP_MODE ME4600_AO_WRAP_MODE | ||
79 | |||
80 | # define ME4600_AO_INF_STOP_MODE 0x0 | ||
81 | # define ME4600_AO_ACQ_STOP_MODE 0x1 | ||
82 | # define ME4600_AO_SCAN_STOP_MODE 0x2 | ||
83 | |||
84 | # ifdef BOSCH //SPECIAL BUILD FOR BOSCH | ||
85 | |||
86 | /* Bits for flags attribute. */ | ||
87 | # define ME4600_AO_FLAGS_BROKEN_PIPE 0x1 | ||
88 | # define ME4600_AO_FLAGS_SW_WRAP_MODE_0 0x2 | ||
89 | # define ME4600_AO_FLAGS_SW_WRAP_MODE_1 0x4 | ||
90 | # define ME4600_AO_FLAGS_SW_WRAP_MODE_MASK (ME4600_AO_FLAGS_SW_WRAP_MODE_0 | ME4600_AO_FLAGS_SW_WRAP_MODE_1) | ||
91 | |||
92 | # define ME4600_AO_FLAGS_SW_WRAP_MODE_NONE 0x0 | ||
93 | # define ME4600_AO_FLAGS_SW_WRAP_MODE_INF 0x2 | ||
94 | # define ME4600_AO_FLAGS_SW_WRAP_MODE_FIN 0x4 | ||
95 | |||
96 | /** | ||
97 | * @brief The ME-4000 analog output subdevice class. | ||
98 | */ | ||
99 | typedef struct me4600_ao_subdevice { | ||
100 | /* Inheritance */ | ||
101 | me_subdevice_t base; /**< The subdevice base class. */ | ||
102 | |||
103 | /* Attributes */ | ||
104 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
105 | spinlock_t *preload_reg_lock; /**< Spin lock to protect #preload_reg from concurrent access. */ | ||
106 | uint32_t *preload_flags; | ||
107 | |||
108 | unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */ | ||
109 | me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. */ | ||
110 | wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ | ||
111 | |||
112 | int single_value; /**< Mirror of the value written in single mode. */ | ||
113 | |||
114 | int volatile flags; /**< Flags used for storing SW wraparound setup and error signalling from ISR. */ | ||
115 | unsigned int wrap_count; /**< The user defined wraparound cycle count. */ | ||
116 | unsigned int wrap_remaining; /**< The wraparound cycle down counter used by a running conversion. */ | ||
117 | unsigned int ao_idx; /**< The index of this analog output on this device. */ | ||
118 | int fifo; /**< If set this device has a FIFO. */ | ||
119 | |||
120 | int bosch_fw; /**< If set the bosch firmware is in PROM. */ | ||
121 | |||
122 | /* Registers */ | ||
123 | uint32_t ctrl_reg; | ||
124 | uint32_t status_reg; | ||
125 | uint32_t fifo_reg; | ||
126 | uint32_t single_reg; | ||
127 | uint32_t timer_reg; | ||
128 | uint32_t irq_status_reg; | ||
129 | uint32_t preload_reg; | ||
130 | uint32_t reg_base; | ||
131 | } me4600_ao_subdevice_t; | ||
132 | |||
133 | /** | ||
134 | * @brief The constructor to generate a ME-4000 analog output subdevice instance for BOSCH project. | ||
135 | * | ||
136 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
137 | * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. | ||
138 | * @param preload_flags Pointer to spin lock protecting the hold&trigger register from concurrent access. | ||
139 | * @param ao_idx Subdevice number. | ||
140 | * @param fifo Flag set if subdevice has hardware FIFO. | ||
141 | * @param irq IRQ number. | ||
142 | * | ||
143 | * @return Pointer to new instance on success.\n | ||
144 | * NULL on error. | ||
145 | */ | ||
146 | me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, | ||
147 | spinlock_t * preload_reg_lock, | ||
148 | uint32_t * preload_flags, | ||
149 | int ao_idx, int fifo, int irq); | ||
150 | |||
151 | # else //~BOSCH | ||
152 | |||
153 | //ME4600_AO_FLAGS_BROKEN_PIPE is OBSOLETE => Now problems are reported in status. | ||
154 | |||
155 | typedef enum ME4600_AO_STATUS { | ||
156 | ao_status_none = 0, | ||
157 | ao_status_single_configured, | ||
158 | ao_status_single_run_wait, | ||
159 | ao_status_single_run, | ||
160 | ao_status_single_end_wait, | ||
161 | ao_status_single_end, | ||
162 | ao_status_stream_configured, | ||
163 | ao_status_stream_run_wait, | ||
164 | ao_status_stream_run, | ||
165 | ao_status_stream_end_wait, | ||
166 | ao_status_stream_end, | ||
167 | ao_status_stream_fifo_error, | ||
168 | ao_status_stream_buffer_error, | ||
169 | ao_status_stream_error, | ||
170 | ao_status_last | ||
171 | } ME4600_AO_STATUS; | ||
172 | |||
173 | typedef struct me4600_ao_timeout { | ||
174 | unsigned long start_time; | ||
175 | unsigned long delay; | ||
176 | } me4600_ao_timeout_t; | ||
177 | |||
178 | /** | ||
179 | * @brief The ME-4600 analog output subdevice class. | ||
180 | */ | ||
181 | typedef struct me4600_ao_subdevice { | ||
182 | /* Inheritance */ | ||
183 | me_subdevice_t base; /**< The subdevice base class. */ | ||
184 | unsigned int ao_idx; /**< The index of this analog output on this device. */ | ||
185 | |||
186 | /* Attributes */ | ||
187 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
188 | spinlock_t *preload_reg_lock; /**< Spin lock to protect preload_reg from concurrent access. */ | ||
189 | |||
190 | uint32_t *preload_flags; | ||
191 | |||
192 | /* Hardware feautres */ | ||
193 | unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */ | ||
194 | int fifo; /**< If set this device has a FIFO. */ | ||
195 | int bitpattern; /**< If set this device use bitpattern. */ | ||
196 | |||
197 | int single_value; /**< Mirror of the output value in single mode. */ | ||
198 | int single_value_in_fifo; /**< Mirror of the value written in single mode. */ | ||
199 | uint32_t ctrl_trg; /**< Mirror of the trigger settings. */ | ||
200 | |||
201 | volatile int mode; /**< Flags used for storing SW wraparound setup*/ | ||
202 | int stop_mode; /**< The user defined stop condition flag. */ | ||
203 | unsigned int start_mode; | ||
204 | unsigned int stop_count; /**< The user defined dates presentation end count. */ | ||
205 | unsigned int stop_data_count; /**< The stop presentation count. */ | ||
206 | unsigned int data_count; /**< The real presentation count. */ | ||
207 | unsigned int preloaded_count; /**< The next data addres in buffer. <= for wraparound mode. */ | ||
208 | int hardware_stop_delay; /**< The time that stop can take. This is only to not show hardware bug to user. */ | ||
209 | |||
210 | volatile enum ME4600_AO_STATUS status; /**< The current stream status flag. */ | ||
211 | me4600_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */ | ||
212 | |||
213 | /* Registers *//**< All registers are 32 bits long. */ | ||
214 | unsigned long ctrl_reg; | ||
215 | unsigned long status_reg; | ||
216 | unsigned long fifo_reg; | ||
217 | unsigned long single_reg; | ||
218 | unsigned long timer_reg; | ||
219 | unsigned long irq_status_reg; | ||
220 | unsigned long preload_reg; | ||
221 | unsigned long reg_base; | ||
222 | |||
223 | /* Software buffer */ | ||
224 | me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. 32 bit long */ | ||
225 | wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ | ||
226 | |||
227 | struct workqueue_struct *me4600_workqueue; | ||
228 | struct delayed_work ao_control_task; | ||
229 | |||
230 | volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ | ||
231 | |||
232 | } me4600_ao_subdevice_t; | ||
233 | |||
234 | /** | ||
235 | * @brief The constructor to generate a ME-4600 analog output subdevice instance. | ||
236 | * | ||
237 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
238 | * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. | ||
239 | * @param preload_flags Pointer to spin lock protecting the hold&trigger register from concurrent access. | ||
240 | * @param ao_idx Subdevice number. | ||
241 | * @param fifo Flag set if subdevice has hardware FIFO. | ||
242 | * @param irq IRQ number. | ||
243 | * @param me4600_wq Queue for asynchronous task (1 queue for all subdevice on 1 board). | ||
244 | * | ||
245 | * @return Pointer to new instance on success.\n | ||
246 | * NULL on error. | ||
247 | */ | ||
248 | me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, | ||
249 | spinlock_t * preload_reg_lock, | ||
250 | uint32_t * preload_flags, | ||
251 | int ao_idx, | ||
252 | int fifo, | ||
253 | int irq, | ||
254 | struct workqueue_struct | ||
255 | *me4600_wq); | ||
256 | |||
257 | # endif //BOSCH | ||
258 | # endif //__KERNEL__ | ||
259 | #endif // ~_ME4600_AO_H_ | ||
diff --git a/drivers/staging/meilhaus/me4600_ao_reg.h b/drivers/staging/meilhaus/me4600_ao_reg.h deleted file mode 100644 index f83d82ecd4bf..000000000000 --- a/drivers/staging/meilhaus/me4600_ao_reg.h +++ /dev/null | |||
@@ -1,113 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ao_reg.h | ||
3 | * | ||
4 | * @brief ME-4000 analog output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_AO_REG_H_ | ||
28 | #define _ME4600_AO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME4600_AO_00_CTRL_REG 0x00 // R/W | ||
33 | #define ME4600_AO_00_STATUS_REG 0x04 // R/_ | ||
34 | #define ME4600_AO_00_FIFO_REG 0x08 // _/W | ||
35 | #define ME4600_AO_00_SINGLE_REG 0x0C // R/W | ||
36 | #define ME4600_AO_00_TIMER_REG 0x10 // _/W | ||
37 | |||
38 | #define ME4600_AO_01_CTRL_REG 0x18 // R/W | ||
39 | #define ME4600_AO_01_STATUS_REG 0x1C // R/_ | ||
40 | #define ME4600_AO_01_FIFO_REG 0x20 // _/W | ||
41 | #define ME4600_AO_01_SINGLE_REG 0x24 // R/W | ||
42 | #define ME4600_AO_01_TIMER_REG 0x28 // _/W | ||
43 | |||
44 | #define ME4600_AO_02_CTRL_REG 0x30 // R/W | ||
45 | #define ME4600_AO_02_STATUS_REG 0x34 // R/_ | ||
46 | #define ME4600_AO_02_FIFO_REG 0x38 // _/W | ||
47 | #define ME4600_AO_02_SINGLE_REG 0x3C // R/W | ||
48 | #define ME4600_AO_02_TIMER_REG 0x40 // _/W | ||
49 | |||
50 | #define ME4600_AO_03_CTRL_REG 0x48 // R/W | ||
51 | #define ME4600_AO_03_STATUS_REG 0x4C // R/_ | ||
52 | #define ME4600_AO_03_FIFO_REG 0x50 // _/W | ||
53 | #define ME4600_AO_03_SINGLE_REG 0x54 // R/W | ||
54 | #define ME4600_AO_03_TIMER_REG 0x58 // _/W | ||
55 | |||
56 | #define ME4600_AO_DEMUX_ADJUST_REG 0xBC // -/W | ||
57 | #define ME4600_AO_DEMUX_ADJUST_VALUE 0x4C | ||
58 | |||
59 | #ifdef BOSCH | ||
60 | # define ME4600_AO_BOSCH_REG 0xC4 | ||
61 | |||
62 | # define ME4600_AO_LOADSETREG_XX 0xB4 // R/W | ||
63 | |||
64 | # define ME4600_AO_CTRL_BIT_MODE_0 0x001 | ||
65 | # define ME4600_AO_CTRL_BIT_MODE_1 0x002 | ||
66 | # define ME4600_AO_CTRL_MASK_MODE 0x003 | ||
67 | |||
68 | #else //~BOSCH | ||
69 | |||
70 | #define ME4600_AO_SYNC_REG 0xB4 // R/W ///ME4600_AO_SYNC_REG <==> ME4600_AO_PRELOAD_REG <==> ME4600_AO_LOADSETREG_XX | ||
71 | |||
72 | # define ME4600_AO_MODE_SINGLE 0x00000000 | ||
73 | # define ME4600_AO_MODE_WRAPAROUND 0x00000001 | ||
74 | # define ME4600_AO_MODE_CONTINUOUS 0x00000002 | ||
75 | # define ME4600_AO_CTRL_MODE_MASK (ME4600_AO_MODE_WRAPAROUND | ME4600_AO_MODE_CONTINUOUS) | ||
76 | #endif //BOSCH | ||
77 | |||
78 | #define ME4600_AO_CTRL_BIT_MODE_WRAPAROUND ME4600_AO_MODE_WRAPAROUND | ||
79 | #define ME4600_AO_CTRL_BIT_MODE_CONTINOUS ME4600_AO_MODE_CONTINUOUS | ||
80 | #define ME4600_AO_CTRL_BIT_STOP 0x00000004 | ||
81 | #define ME4600_AO_CTRL_BIT_ENABLE_FIFO 0x00000008 | ||
82 | #define ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG 0x00000010 | ||
83 | #define ME4600_AO_CTRL_BIT_EX_TRIG_EDGE 0x00000020 | ||
84 | #define ME4600_AO_CTRL_BIT_IMMEDIATE_STOP 0x00000080 | ||
85 | #define ME4600_AO_CTRL_BIT_ENABLE_DO 0x00000100 | ||
86 | #define ME4600_AO_CTRL_BIT_ENABLE_IRQ 0x00000200 | ||
87 | #define ME4600_AO_CTRL_BIT_RESET_IRQ 0x00000400 | ||
88 | #define ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH 0x00000800 | ||
89 | /* | ||
90 | #define ME4600_AO_SYNC_HOLD_0 0x00000001 | ||
91 | #define ME4600_AO_SYNC_HOLD_1 0x00000002 | ||
92 | #define ME4600_AO_SYNC_HOLD_2 0x00000004 | ||
93 | #define ME4600_AO_SYNC_HOLD_3 0x00000008 | ||
94 | */ | ||
95 | #define ME4600_AO_SYNC_HOLD 0x00000001 | ||
96 | |||
97 | /* | ||
98 | #define ME4600_AO_SYNC_EXT_TRIG_0 0x00010000 | ||
99 | #define ME4600_AO_SYNC_EXT_TRIG_1 0x00020000 | ||
100 | #define ME4600_AO_SYNC_EXT_TRIG_2 0x00040000 | ||
101 | #define ME4600_AO_SYNC_EXT_TRIG_3 0x00080000 | ||
102 | */ | ||
103 | #define ME4600_AO_SYNC_EXT_TRIG 0x00010000 | ||
104 | |||
105 | #define ME4600_AO_EXT_TRIG 0x80000000 | ||
106 | |||
107 | #define ME4600_AO_STATUS_BIT_FSM 0x00000001 | ||
108 | #define ME4600_AO_STATUS_BIT_FF 0x00000002 | ||
109 | #define ME4600_AO_STATUS_BIT_HF 0x00000004 | ||
110 | #define ME4600_AO_STATUS_BIT_EF 0x00000008 | ||
111 | |||
112 | #endif | ||
113 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_device.c b/drivers/staging/meilhaus/me4600_device.c deleted file mode 100644 index 457666ef61a5..000000000000 --- a/drivers/staging/meilhaus/me4600_device.c +++ /dev/null | |||
@@ -1,371 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_device.c | ||
3 | * | ||
4 | * @brief ME-4600 device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include "meids.h" | ||
42 | #include "meerror.h" | ||
43 | #include "mecommon.h" | ||
44 | #include "meinternal.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "medevice.h" | ||
48 | #include "me4600_device.h" | ||
49 | #include "meplx_reg.h" | ||
50 | |||
51 | #include "mefirmware.h" | ||
52 | |||
53 | #include "mesubdevice.h" | ||
54 | #include "me4600_do.h" | ||
55 | #include "me4600_di.h" | ||
56 | #include "me4600_dio.h" | ||
57 | #include "me8254.h" | ||
58 | #include "me4600_ai.h" | ||
59 | #include "me4600_ao.h" | ||
60 | #include "me4600_ext_irq.h" | ||
61 | |||
62 | /** | ||
63 | * @brief Global variable. | ||
64 | * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts). | ||
65 | */ | ||
66 | static struct workqueue_struct *me4600_workqueue; | ||
67 | |||
68 | #ifdef BOSCH | ||
69 | me_device_t *me4600_pci_constructor(struct pci_dev *pci_device, int me_bosch_fw) | ||
70 | #else //~BOSCH | ||
71 | me_device_t *me4600_pci_constructor(struct pci_dev *pci_device) | ||
72 | #endif //BOSCH | ||
73 | { | ||
74 | me4600_device_t *me4600_device; | ||
75 | me_subdevice_t *subdevice; | ||
76 | unsigned int version_idx; | ||
77 | int err; | ||
78 | int i; | ||
79 | |||
80 | PDEBUG("executed.\n"); | ||
81 | |||
82 | // Allocate structure for device instance. | ||
83 | me4600_device = kmalloc(sizeof(me4600_device_t), GFP_KERNEL); | ||
84 | |||
85 | if (!me4600_device) { | ||
86 | PERROR("Cannot get memory for ME-4600 device instance.\n"); | ||
87 | return NULL; | ||
88 | } | ||
89 | |||
90 | memset(me4600_device, 0, sizeof(me4600_device_t)); | ||
91 | |||
92 | // Initialize base class structure. | ||
93 | err = me_device_pci_init((me_device_t *) me4600_device, pci_device); | ||
94 | |||
95 | if (err) { | ||
96 | kfree(me4600_device); | ||
97 | PERROR("Cannot initialize device base class.\n"); | ||
98 | return NULL; | ||
99 | } | ||
100 | // Download the xilinx firmware. | ||
101 | if (me4600_device->base.info.pci.device_id == PCI_DEVICE_ID_MEILHAUS_ME4610) { //Jekyll <=> me4610 | ||
102 | err = | ||
103 | me_xilinx_download(me4600_device->base.info.pci. | ||
104 | reg_bases[1], | ||
105 | me4600_device->base.info.pci. | ||
106 | reg_bases[5], &pci_device->dev, | ||
107 | "me4610.bin"); | ||
108 | } else { // General me4600 firmware | ||
109 | #ifdef BOSCH | ||
110 | err = | ||
111 | me_xilinx_download(me4600_device->base.info.pci. | ||
112 | reg_bases[1], | ||
113 | me4600_device->base.info.pci. | ||
114 | reg_bases[5], &pci_device->dev, | ||
115 | (me_bosch_fw) ? "me4600_bosch.bin" : | ||
116 | "me4600.bin"); | ||
117 | #else //~BOSCH | ||
118 | err = | ||
119 | me_xilinx_download(me4600_device->base.info.pci. | ||
120 | reg_bases[1], | ||
121 | me4600_device->base.info.pci. | ||
122 | reg_bases[5], &pci_device->dev, | ||
123 | "me4600.bin"); | ||
124 | #endif | ||
125 | } | ||
126 | |||
127 | if (err) { | ||
128 | me_device_deinit((me_device_t *) me4600_device); | ||
129 | kfree(me4600_device); | ||
130 | PERROR("Cannot download firmware.\n"); | ||
131 | return NULL; | ||
132 | } | ||
133 | // Get the index in the device version information table. | ||
134 | version_idx = | ||
135 | me4600_versions_get_device_index(me4600_device->base.info.pci. | ||
136 | device_id); | ||
137 | |||
138 | // Initialize spin locks. | ||
139 | spin_lock_init(&me4600_device->preload_reg_lock); | ||
140 | |||
141 | me4600_device->preload_flags = 0; | ||
142 | |||
143 | spin_lock_init(&me4600_device->dio_lock); | ||
144 | spin_lock_init(&me4600_device->ai_ctrl_lock); | ||
145 | spin_lock_init(&me4600_device->ctr_ctrl_reg_lock); | ||
146 | spin_lock_init(&me4600_device->ctr_clk_src_reg_lock); | ||
147 | |||
148 | // Create digital input instances. | ||
149 | for (i = 0; i < me4600_versions[version_idx].di_subdevices; i++) { | ||
150 | subdevice = | ||
151 | (me_subdevice_t *) me4600_di_constructor(me4600_device-> | ||
152 | base.info.pci. | ||
153 | reg_bases[2], | ||
154 | &me4600_device-> | ||
155 | dio_lock); | ||
156 | |||
157 | if (!subdevice) { | ||
158 | me_device_deinit((me_device_t *) me4600_device); | ||
159 | kfree(me4600_device); | ||
160 | PERROR("Cannot get memory for subdevice.\n"); | ||
161 | return NULL; | ||
162 | } | ||
163 | |||
164 | me_slist_add_subdevice_tail(&me4600_device->base.slist, | ||
165 | subdevice); | ||
166 | } | ||
167 | |||
168 | // Create digital output instances. | ||
169 | for (i = 0; i < me4600_versions[version_idx].do_subdevices; i++) { | ||
170 | subdevice = | ||
171 | (me_subdevice_t *) me4600_do_constructor(me4600_device-> | ||
172 | base.info.pci. | ||
173 | reg_bases[2], | ||
174 | &me4600_device-> | ||
175 | dio_lock); | ||
176 | |||
177 | if (!subdevice) { | ||
178 | me_device_deinit((me_device_t *) me4600_device); | ||
179 | kfree(me4600_device); | ||
180 | PERROR("Cannot get memory for subdevice.\n"); | ||
181 | return NULL; | ||
182 | } | ||
183 | |||
184 | me_slist_add_subdevice_tail(&me4600_device->base.slist, | ||
185 | subdevice); | ||
186 | } | ||
187 | |||
188 | // Create digital input/output instances. | ||
189 | for (i = 0; i < me4600_versions[version_idx].dio_subdevices; i++) { | ||
190 | subdevice = | ||
191 | (me_subdevice_t *) me4600_dio_constructor(me4600_device-> | ||
192 | base.info.pci. | ||
193 | reg_bases[2], | ||
194 | me4600_versions | ||
195 | [version_idx]. | ||
196 | do_subdevices + | ||
197 | me4600_versions | ||
198 | [version_idx]. | ||
199 | di_subdevices + i, | ||
200 | &me4600_device-> | ||
201 | dio_lock); | ||
202 | |||
203 | if (!subdevice) { | ||
204 | me_device_deinit((me_device_t *) me4600_device); | ||
205 | kfree(me4600_device); | ||
206 | PERROR("Cannot get memory for subdevice.\n"); | ||
207 | return NULL; | ||
208 | } | ||
209 | |||
210 | me_slist_add_subdevice_tail(&me4600_device->base.slist, | ||
211 | subdevice); | ||
212 | } | ||
213 | |||
214 | // Create analog input instances. | ||
215 | for (i = 0; i < me4600_versions[version_idx].ai_subdevices; i++) { | ||
216 | subdevice = | ||
217 | (me_subdevice_t *) me4600_ai_constructor(me4600_device-> | ||
218 | base.info.pci. | ||
219 | reg_bases[2], | ||
220 | me4600_versions | ||
221 | [version_idx]. | ||
222 | ai_channels, | ||
223 | me4600_versions | ||
224 | [version_idx]. | ||
225 | ai_ranges, | ||
226 | me4600_versions | ||
227 | [version_idx]. | ||
228 | ai_isolated, | ||
229 | me4600_versions | ||
230 | [version_idx]. | ||
231 | ai_sh, | ||
232 | me4600_device-> | ||
233 | base.irq, | ||
234 | &me4600_device-> | ||
235 | ai_ctrl_lock, | ||
236 | me4600_workqueue); | ||
237 | |||
238 | if (!subdevice) { | ||
239 | me_device_deinit((me_device_t *) me4600_device); | ||
240 | kfree(me4600_device); | ||
241 | PERROR("Cannot get memory for subdevice.\n"); | ||
242 | return NULL; | ||
243 | } | ||
244 | |||
245 | me_slist_add_subdevice_tail(&me4600_device->base.slist, | ||
246 | subdevice); | ||
247 | } | ||
248 | |||
249 | // Create analog output instances. | ||
250 | for (i = 0; i < me4600_versions[version_idx].ao_subdevices; i++) { | ||
251 | #ifdef BOSCH | ||
252 | subdevice = | ||
253 | (me_subdevice_t *) me4600_ao_constructor(me4600_device-> | ||
254 | base.info.pci. | ||
255 | reg_bases[2], | ||
256 | &me4600_device-> | ||
257 | preload_reg_lock, | ||
258 | &me4600_device-> | ||
259 | preload_flags, i, | ||
260 | me4600_versions | ||
261 | [version_idx]. | ||
262 | ao_fifo, | ||
263 | me4600_device-> | ||
264 | base.irq); | ||
265 | #else //~BOSCH | ||
266 | subdevice = | ||
267 | (me_subdevice_t *) me4600_ao_constructor(me4600_device-> | ||
268 | base.info.pci. | ||
269 | reg_bases[2], | ||
270 | &me4600_device-> | ||
271 | preload_reg_lock, | ||
272 | &me4600_device-> | ||
273 | preload_flags, i, | ||
274 | me4600_versions | ||
275 | [version_idx]. | ||
276 | ao_fifo, | ||
277 | me4600_device-> | ||
278 | base.irq, | ||
279 | me4600_workqueue); | ||
280 | #endif | ||
281 | |||
282 | if (!subdevice) { | ||
283 | me_device_deinit((me_device_t *) me4600_device); | ||
284 | kfree(me4600_device); | ||
285 | PERROR("Cannot get memory for subdevice.\n"); | ||
286 | return NULL; | ||
287 | } | ||
288 | |||
289 | me_slist_add_subdevice_tail(&me4600_device->base.slist, | ||
290 | subdevice); | ||
291 | } | ||
292 | |||
293 | // Create counter instances. | ||
294 | for (i = 0; i < me4600_versions[version_idx].ctr_subdevices; i++) { | ||
295 | subdevice = | ||
296 | (me_subdevice_t *) me8254_constructor(me4600_device->base. | ||
297 | info.pci.device_id, | ||
298 | me4600_device->base. | ||
299 | info.pci.reg_bases[3], | ||
300 | 0, i, | ||
301 | &me4600_device-> | ||
302 | ctr_ctrl_reg_lock, | ||
303 | &me4600_device-> | ||
304 | ctr_clk_src_reg_lock); | ||
305 | |||
306 | if (!subdevice) { | ||
307 | me_device_deinit((me_device_t *) me4600_device); | ||
308 | kfree(me4600_device); | ||
309 | PERROR("Cannot get memory for subdevice.\n"); | ||
310 | return NULL; | ||
311 | } | ||
312 | |||
313 | me_slist_add_subdevice_tail(&me4600_device->base.slist, | ||
314 | subdevice); | ||
315 | } | ||
316 | |||
317 | // Create external interrupt instances. | ||
318 | for (i = 0; i < me4600_versions[version_idx].ext_irq_subdevices; i++) { | ||
319 | subdevice = | ||
320 | (me_subdevice_t *) | ||
321 | me4600_ext_irq_constructor(me4600_device->base.info.pci. | ||
322 | reg_bases[2], | ||
323 | me4600_device->base.irq, | ||
324 | &me4600_device->ai_ctrl_lock); | ||
325 | |||
326 | if (!subdevice) { | ||
327 | me_device_deinit((me_device_t *) me4600_device); | ||
328 | kfree(me4600_device); | ||
329 | PERROR("Cannot get memory for subdevice.\n"); | ||
330 | return NULL; | ||
331 | } | ||
332 | |||
333 | me_slist_add_subdevice_tail(&me4600_device->base.slist, | ||
334 | subdevice); | ||
335 | } | ||
336 | |||
337 | return (me_device_t *) me4600_device; | ||
338 | } | ||
339 | EXPORT_SYMBOL(me4600_pci_constructor); | ||
340 | |||
341 | // Init and exit of module. | ||
342 | |||
343 | static int __init me4600_init(void) | ||
344 | { | ||
345 | PDEBUG("executed.\n"); | ||
346 | |||
347 | #ifndef BOSCH | ||
348 | me4600_workqueue = create_singlethread_workqueue("me4600"); | ||
349 | #endif | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static void __exit me4600_exit(void) | ||
354 | { | ||
355 | PDEBUG("executed.\n"); | ||
356 | |||
357 | #ifndef BOSCH | ||
358 | flush_workqueue(me4600_workqueue); | ||
359 | destroy_workqueue(me4600_workqueue); | ||
360 | #endif | ||
361 | } | ||
362 | |||
363 | module_init(me4600_init); | ||
364 | module_exit(me4600_exit); | ||
365 | |||
366 | // Administrative stuff for modinfo. | ||
367 | MODULE_AUTHOR | ||
368 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
369 | MODULE_DESCRIPTION("Device Driver Module for ME-46xx Devices"); | ||
370 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-46xx Devices"); | ||
371 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me4600_device.h b/drivers/staging/meilhaus/me4600_device.h deleted file mode 100644 index c755c574cda2..000000000000 --- a/drivers/staging/meilhaus/me4600_device.h +++ /dev/null | |||
@@ -1,151 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_device.h | ||
3 | * | ||
4 | * @brief ME-4600 device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef _ME4600_DEVICE_H | ||
29 | #define _ME4600_DEVICE_H | ||
30 | |||
31 | #include <linux/pci.h> | ||
32 | #include <linux/spinlock.h> | ||
33 | |||
34 | #include "medevice.h" | ||
35 | |||
36 | #ifdef __KERNEL__ | ||
37 | |||
38 | /** | ||
39 | * @brief Structure holding ME-4600 device capabilities. | ||
40 | */ | ||
41 | typedef struct me4600_version { | ||
42 | uint16_t device_id; | ||
43 | unsigned int do_subdevices; | ||
44 | unsigned int di_subdevices; | ||
45 | unsigned int dio_subdevices; | ||
46 | unsigned int ctr_subdevices; | ||
47 | unsigned int ai_subdevices; | ||
48 | unsigned int ai_channels; | ||
49 | unsigned int ai_ranges; | ||
50 | unsigned int ai_isolated; | ||
51 | unsigned int ai_sh; | ||
52 | unsigned int ao_subdevices; | ||
53 | unsigned int ao_fifo; //How many devices have FIFO | ||
54 | unsigned int ext_irq_subdevices; | ||
55 | } me4600_version_t; | ||
56 | |||
57 | /** | ||
58 | * @brief ME-4600 device capabilities. | ||
59 | */ | ||
60 | static me4600_version_t me4600_versions[] = { | ||
61 | {PCI_DEVICE_ID_MEILHAUS_ME4610, 0, 0, 4, 3, 1, 16, 1, 0, 0, 0, 0, 1}, | ||
62 | |||
63 | {PCI_DEVICE_ID_MEILHAUS_ME4650, 0, 0, 4, 0, 1, 16, 4, 0, 0, 0, 0, 1}, | ||
64 | |||
65 | {PCI_DEVICE_ID_MEILHAUS_ME4660, 0, 0, 4, 3, 1, 16, 4, 0, 0, 2, 0, 1}, | ||
66 | {PCI_DEVICE_ID_MEILHAUS_ME4660I, 1, 1, 2, 3, 1, 16, 4, 1, 0, 2, 0, 1}, | ||
67 | {PCI_DEVICE_ID_MEILHAUS_ME4660S, 0, 0, 4, 3, 1, 16, 4, 0, 1, 2, 0, 1}, | ||
68 | {PCI_DEVICE_ID_MEILHAUS_ME4660IS, 1, 1, 2, 3, 1, 16, 4, 1, 1, 2, 0, 1}, | ||
69 | |||
70 | {PCI_DEVICE_ID_MEILHAUS_ME4670, 0, 0, 4, 3, 1, 32, 4, 0, 0, 4, 0, 1}, | ||
71 | {PCI_DEVICE_ID_MEILHAUS_ME4670I, 1, 1, 2, 3, 1, 32, 4, 1, 0, 4, 0, 1}, | ||
72 | {PCI_DEVICE_ID_MEILHAUS_ME4670S, 0, 0, 4, 3, 1, 32, 4, 0, 1, 4, 0, 1}, | ||
73 | {PCI_DEVICE_ID_MEILHAUS_ME4670IS, 1, 1, 2, 3, 1, 32, 4, 1, 1, 4, 0, 1}, | ||
74 | |||
75 | {PCI_DEVICE_ID_MEILHAUS_ME4680, 0, 0, 4, 3, 1, 32, 4, 0, 0, 4, 4, 1}, | ||
76 | {PCI_DEVICE_ID_MEILHAUS_ME4680I, 1, 1, 2, 3, 1, 32, 4, 1, 0, 4, 4, 1}, | ||
77 | {PCI_DEVICE_ID_MEILHAUS_ME4680S, 0, 0, 4, 3, 1, 32, 4, 0, 1, 4, 4, 1}, | ||
78 | {PCI_DEVICE_ID_MEILHAUS_ME4680IS, 1, 1, 2, 3, 1, 32, 4, 1, 1, 4, 4, 1}, | ||
79 | |||
80 | {0}, | ||
81 | }; | ||
82 | |||
83 | #define ME4600_DEVICE_VERSIONS (ARRAY_SIZE(me4600_versions) - 1) /**< Returns the number of entries in #me4600_versions. */ | ||
84 | |||
85 | /** | ||
86 | * @brief Returns the index of the device entry in #me4600_versions. | ||
87 | * | ||
88 | * @param device_id The PCI device id of the device to query. | ||
89 | * @return The index of the device in #me4600_versions. | ||
90 | */ | ||
91 | static inline unsigned int me4600_versions_get_device_index(uint16_t device_id) | ||
92 | { | ||
93 | unsigned int i; | ||
94 | for (i = 0; i < ME4600_DEVICE_VERSIONS; i++) | ||
95 | if (me4600_versions[i].device_id == device_id) | ||
96 | break; | ||
97 | return i; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * @brief The ME-4600 device class structure. | ||
102 | */ | ||
103 | typedef struct me4600_device { | ||
104 | me_device_t base; /**< The Meilhaus device base class. */ | ||
105 | |||
106 | /* Child class attributes. */ | ||
107 | spinlock_t preload_reg_lock; /**< Guards the preload register of the anaolog output devices. */ | ||
108 | unsigned int preload_flags; /**< Used in conjunction with #preload_reg_lock. */ | ||
109 | spinlock_t dio_lock; /**< Locks the control register of the digital input/output subdevices. */ | ||
110 | spinlock_t ai_ctrl_lock; /**< Locks the control register of the analog input subdevice. */ | ||
111 | spinlock_t ctr_ctrl_reg_lock; /**< Locks the counter control register. */ | ||
112 | spinlock_t ctr_clk_src_reg_lock; /**< Not used on this device but needed for the me8254 subdevice constructor call. */ | ||
113 | } me4600_device_t; | ||
114 | |||
115 | /** | ||
116 | * @brief The ME-4600 device class constructor. | ||
117 | * | ||
118 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
119 | * @param me_bosch_fw If set the device shall use the bosch firmware. (Only for special BOSCH build) | ||
120 | * | ||
121 | * @return On succes a new ME-4600 device instance. \n | ||
122 | * NULL on error. | ||
123 | */ | ||
124 | |||
125 | #ifdef BOSCH | ||
126 | /** | ||
127 | * @brief The ME-4600 device class constructor. | ||
128 | * | ||
129 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
130 | * @param me_bosch_fw If set the device shall use the bosch firmware. | ||
131 | * | ||
132 | * @return On succes a new ME-4600 device instance. \n | ||
133 | * NULL on error. | ||
134 | */ | ||
135 | me_device_t *me4600_pci_constructor(struct pci_dev *pci_device, int me_bosch_fw) | ||
136 | __attribute__ ((weak)); | ||
137 | #else //~BOSCH | ||
138 | /** | ||
139 | * @brief The ME-4600 device class constructor. | ||
140 | * | ||
141 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
142 | * | ||
143 | * @return On succes a new ME-4600 device instance. \n | ||
144 | * NULL on error. | ||
145 | */ | ||
146 | me_device_t *me4600_pci_constructor(struct pci_dev *pci_device) | ||
147 | __attribute__ ((weak)); | ||
148 | #endif | ||
149 | |||
150 | #endif | ||
151 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_di.c b/drivers/staging/meilhaus/me4600_di.c deleted file mode 100644 index e107e5061388..000000000000 --- a/drivers/staging/meilhaus/me4600_di.c +++ /dev/null | |||
@@ -1,256 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_di.c | ||
3 | * | ||
4 | * @brief ME-4000 digital input subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me4600_dio_reg.h" | ||
48 | #include "me4600_di.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me4600_di_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | me4600_di_subdevice_t *instance; | ||
62 | uint32_t mode; | ||
63 | |||
64 | PDEBUG("executed.\n"); | ||
65 | |||
66 | instance = (me4600_di_subdevice_t *) subdevice; | ||
67 | |||
68 | if (flags) { | ||
69 | PERROR("Invalid flag specified.\n"); | ||
70 | return ME_ERRNO_INVALID_FLAGS; | ||
71 | } | ||
72 | |||
73 | ME_SUBDEVICE_ENTER; | ||
74 | |||
75 | spin_lock(&instance->subdevice_lock); | ||
76 | spin_lock(instance->ctrl_reg_lock); | ||
77 | mode = inl(instance->ctrl_reg); | ||
78 | mode &= ~(ME4600_DIO_CTRL_BIT_MODE_2 | ME4600_DIO_CTRL_BIT_MODE_3); //0xFFF3 | ||
79 | outl(mode, instance->ctrl_reg); | ||
80 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
81 | instance->ctrl_reg - instance->reg_base, mode); | ||
82 | spin_unlock(instance->ctrl_reg_lock); | ||
83 | |||
84 | outl(0, instance->port_reg); | ||
85 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
86 | instance->port_reg - instance->reg_base, 0); | ||
87 | spin_unlock(&instance->subdevice_lock); | ||
88 | |||
89 | ME_SUBDEVICE_EXIT; | ||
90 | |||
91 | return ME_ERRNO_SUCCESS; | ||
92 | } | ||
93 | |||
94 | static int me4600_di_io_single_config(me_subdevice_t *subdevice, | ||
95 | struct file *filep, | ||
96 | int channel, | ||
97 | int single_config, | ||
98 | int ref, | ||
99 | int trig_chan, | ||
100 | int trig_type, int trig_edge, int flags) | ||
101 | { | ||
102 | int err = ME_ERRNO_SUCCESS; | ||
103 | me4600_di_subdevice_t *instance; | ||
104 | |||
105 | PDEBUG("executed.\n"); | ||
106 | |||
107 | instance = (me4600_di_subdevice_t *) subdevice; | ||
108 | |||
109 | ME_SUBDEVICE_ENTER; | ||
110 | |||
111 | switch (flags) { | ||
112 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
113 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
114 | if (channel == 0) { | ||
115 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
116 | } else { | ||
117 | PERROR("Invalid port direction specified.\n"); | ||
118 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
119 | } | ||
120 | } else { | ||
121 | PERROR("Invalid channel number.\n"); | ||
122 | err = ME_ERRNO_INVALID_CHANNEL; | ||
123 | } | ||
124 | break; | ||
125 | |||
126 | default: | ||
127 | PERROR("Invalid flags specified.\n"); | ||
128 | err = ME_ERRNO_INVALID_FLAGS; | ||
129 | } | ||
130 | |||
131 | ME_SUBDEVICE_EXIT; | ||
132 | |||
133 | return err; | ||
134 | } | ||
135 | |||
136 | static int me4600_di_io_single_read(me_subdevice_t *subdevice, | ||
137 | struct file *filep, | ||
138 | int channel, | ||
139 | int *value, int time_out, int flags) | ||
140 | { | ||
141 | me4600_di_subdevice_t *instance; | ||
142 | int err = ME_ERRNO_SUCCESS; | ||
143 | |||
144 | PDEBUG("executed.\n"); | ||
145 | |||
146 | instance = (me4600_di_subdevice_t *) subdevice; | ||
147 | |||
148 | ME_SUBDEVICE_ENTER; | ||
149 | |||
150 | switch (flags) { | ||
151 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
152 | if ((channel >= 0) && (channel < 8)) { | ||
153 | *value = inl(instance->port_reg) & (0x1 << channel); | ||
154 | } else { | ||
155 | PERROR("Invalid bit number specified.\n"); | ||
156 | err = ME_ERRNO_INVALID_CHANNEL; | ||
157 | } | ||
158 | break; | ||
159 | |||
160 | case ME_IO_SINGLE_NO_FLAGS: | ||
161 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
162 | if (channel == 0) { | ||
163 | *value = inl(instance->port_reg) & 0xFF; | ||
164 | } else { | ||
165 | PERROR("Invalid byte number specified.\n"); | ||
166 | err = ME_ERRNO_INVALID_CHANNEL; | ||
167 | } | ||
168 | break; | ||
169 | |||
170 | default: | ||
171 | PERROR("Invalid flags specified.\n"); | ||
172 | err = ME_ERRNO_INVALID_FLAGS; | ||
173 | } | ||
174 | |||
175 | ME_SUBDEVICE_EXIT; | ||
176 | |||
177 | return err; | ||
178 | } | ||
179 | |||
180 | static int me4600_di_query_number_channels(me_subdevice_t *subdevice, | ||
181 | int *number) | ||
182 | { | ||
183 | PDEBUG("executed.\n"); | ||
184 | *number = 8; | ||
185 | return ME_ERRNO_SUCCESS; | ||
186 | } | ||
187 | |||
188 | static int me4600_di_query_subdevice_type(me_subdevice_t *subdevice, | ||
189 | int *type, int *subtype) | ||
190 | { | ||
191 | PDEBUG("executed.\n"); | ||
192 | *type = ME_TYPE_DI; | ||
193 | *subtype = ME_SUBTYPE_SINGLE; | ||
194 | return ME_ERRNO_SUCCESS; | ||
195 | } | ||
196 | |||
197 | static int me4600_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
198 | { | ||
199 | PDEBUG("executed.\n"); | ||
200 | *caps = 0; | ||
201 | return ME_ERRNO_SUCCESS; | ||
202 | } | ||
203 | |||
204 | me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base, | ||
205 | spinlock_t *ctrl_reg_lock) | ||
206 | { | ||
207 | me4600_di_subdevice_t *subdevice; | ||
208 | int err; | ||
209 | |||
210 | PDEBUG("executed.\n"); | ||
211 | |||
212 | /* Allocate memory for subdevice instance */ | ||
213 | subdevice = kmalloc(sizeof(me4600_di_subdevice_t), GFP_KERNEL); | ||
214 | |||
215 | if (!subdevice) { | ||
216 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
217 | return NULL; | ||
218 | } | ||
219 | |||
220 | memset(subdevice, 0, sizeof(me4600_di_subdevice_t)); | ||
221 | |||
222 | /* Initialize subdevice base class */ | ||
223 | err = me_subdevice_init(&subdevice->base); | ||
224 | |||
225 | if (err) { | ||
226 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
227 | kfree(subdevice); | ||
228 | return NULL; | ||
229 | } | ||
230 | // Initialize spin locks. | ||
231 | spin_lock_init(&subdevice->subdevice_lock); | ||
232 | |||
233 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
234 | |||
235 | /* Save the subdevice index */ | ||
236 | subdevice->port_reg = reg_base + ME4600_DIO_PORT_1_REG; | ||
237 | subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG; | ||
238 | #ifdef MEDEBUG_DEBUG_REG | ||
239 | subdevice->reg_base = reg_base; | ||
240 | #endif | ||
241 | |||
242 | /* Overload base class methods. */ | ||
243 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
244 | me4600_di_io_reset_subdevice; | ||
245 | subdevice->base.me_subdevice_io_single_config = | ||
246 | me4600_di_io_single_config; | ||
247 | subdevice->base.me_subdevice_io_single_read = me4600_di_io_single_read; | ||
248 | subdevice->base.me_subdevice_query_number_channels = | ||
249 | me4600_di_query_number_channels; | ||
250 | subdevice->base.me_subdevice_query_subdevice_type = | ||
251 | me4600_di_query_subdevice_type; | ||
252 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
253 | me4600_di_query_subdevice_caps; | ||
254 | |||
255 | return subdevice; | ||
256 | } | ||
diff --git a/drivers/staging/meilhaus/me4600_di.h b/drivers/staging/meilhaus/me4600_di.h deleted file mode 100644 index ec8b175755be..000000000000 --- a/drivers/staging/meilhaus/me4600_di.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_di.h | ||
3 | * | ||
4 | * @brief ME-4000 digital input subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_DI_H_ | ||
28 | #define _ME4600_DI_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me4600_di_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | |||
45 | unsigned long port_reg; /**< Register holding the port status. */ | ||
46 | unsigned long ctrl_reg; /**< Register to configure the port direction. */ | ||
47 | #ifdef MEDEBUG_DEBUG_REG | ||
48 | unsigned long reg_base; | ||
49 | #endif | ||
50 | } me4600_di_subdevice_t; | ||
51 | |||
52 | /** | ||
53 | * @brief The constructor to generate a ME-4000 digital input subdevice instance. | ||
54 | * | ||
55 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
56 | * | ||
57 | * @return Pointer to new instance on success.\n | ||
58 | * NULL on error. | ||
59 | */ | ||
60 | me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base, | ||
61 | spinlock_t * ctrl_reg_lock); | ||
62 | |||
63 | #endif | ||
64 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_dio.c b/drivers/staging/meilhaus/me4600_dio.c deleted file mode 100644 index baa28ff6b6bd..000000000000 --- a/drivers/staging/meilhaus/me4600_dio.c +++ /dev/null | |||
@@ -1,510 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_dio.c | ||
3 | * | ||
4 | * @brief ME-4000 digital input/output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me4600_dio_reg.h" | ||
48 | #include "me4600_dio.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me4600_dio_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | me4600_dio_subdevice_t *instance; | ||
62 | uint32_t mode; | ||
63 | |||
64 | PDEBUG("executed.\n"); | ||
65 | |||
66 | instance = (me4600_dio_subdevice_t *) subdevice; | ||
67 | |||
68 | if (flags) { | ||
69 | PERROR("Invalid flag specified.\n"); | ||
70 | return ME_ERRNO_INVALID_FLAGS; | ||
71 | } | ||
72 | |||
73 | ME_SUBDEVICE_ENTER; | ||
74 | |||
75 | /* Set port to input mode */ | ||
76 | spin_lock(&instance->subdevice_lock); | ||
77 | spin_lock(instance->ctrl_reg_lock); | ||
78 | mode = inl(instance->ctrl_reg); | ||
79 | mode &= | ||
80 | ~((ME4600_DIO_CTRL_BIT_MODE_0 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
81 | (instance->dio_idx * 2)); | ||
82 | outl(mode, instance->ctrl_reg); | ||
83 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
84 | instance->ctrl_reg - instance->reg_base, mode); | ||
85 | spin_unlock(instance->ctrl_reg_lock); | ||
86 | |||
87 | outl(0, instance->port_reg); | ||
88 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
89 | instance->port_reg - instance->reg_base, 0); | ||
90 | spin_unlock(&instance->subdevice_lock); | ||
91 | |||
92 | ME_SUBDEVICE_EXIT; | ||
93 | |||
94 | return ME_ERRNO_SUCCESS; | ||
95 | } | ||
96 | |||
97 | static int me4600_dio_io_single_config(me_subdevice_t *subdevice, | ||
98 | struct file *filep, | ||
99 | int channel, | ||
100 | int single_config, | ||
101 | int ref, | ||
102 | int trig_chan, | ||
103 | int trig_type, int trig_edge, int flags) | ||
104 | { | ||
105 | me4600_dio_subdevice_t *instance; | ||
106 | int err = ME_ERRNO_SUCCESS; | ||
107 | uint32_t mode; | ||
108 | uint32_t size = | ||
109 | flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE | ||
110 | | ME_IO_SINGLE_CONFIG_DIO_WORD | | ||
111 | ME_IO_SINGLE_CONFIG_DIO_DWORD); | ||
112 | uint32_t mask; | ||
113 | |||
114 | PDEBUG("executed.\n"); | ||
115 | |||
116 | instance = (me4600_dio_subdevice_t *) subdevice; | ||
117 | |||
118 | ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); | ||
119 | spin_lock(instance->ctrl_reg_lock); | ||
120 | mode = inl(instance->ctrl_reg); | ||
121 | switch (size) { | ||
122 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
123 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
124 | if (channel == 0) { | ||
125 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
126 | mode &= | ||
127 | ~((ME4600_DIO_CTRL_BIT_MODE_0 | | ||
128 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
129 | (instance->dio_idx * 2)); | ||
130 | } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
131 | mode &= | ||
132 | ~((ME4600_DIO_CTRL_BIT_MODE_0 | | ||
133 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
134 | (instance->dio_idx * 2)); | ||
135 | mode |= | ||
136 | ME4600_DIO_CTRL_BIT_MODE_0 << (instance-> | ||
137 | dio_idx * 2); | ||
138 | } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) { | ||
139 | mask = | ||
140 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
141 | ME4600_DIO_CTRL_BIT_MODE_1) << (instance-> | ||
142 | dio_idx * | ||
143 | 2); | ||
144 | mask |= | ||
145 | ME4600_DIO_CTRL_BIT_FUNCTION_0 | | ||
146 | ME4600_DIO_CTRL_BIT_FUNCTION_1; | ||
147 | mask |= | ||
148 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << | ||
149 | instance->dio_idx; | ||
150 | mode &= ~mask; | ||
151 | |||
152 | if (ref == ME_REF_DIO_FIFO_LOW) { | ||
153 | mode |= | ||
154 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
155 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
156 | (instance->dio_idx * 2); | ||
157 | mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1; | ||
158 | } else if (ref == ME_REF_DIO_FIFO_HIGH) { | ||
159 | mode |= | ||
160 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
161 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
162 | (instance->dio_idx * 2); | ||
163 | mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1; | ||
164 | mode |= | ||
165 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << | ||
166 | instance->dio_idx; | ||
167 | } else { | ||
168 | PERROR | ||
169 | ("Invalid port reference specified.\n"); | ||
170 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
171 | } | ||
172 | } else if (single_config == | ||
173 | ME_SINGLE_CONFIG_DIO_DEMUX32) { | ||
174 | mask = | ||
175 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
176 | ME4600_DIO_CTRL_BIT_MODE_1) << (instance-> | ||
177 | dio_idx * | ||
178 | 2); | ||
179 | mask |= | ||
180 | ME4600_DIO_CTRL_BIT_FUNCTION_0 | | ||
181 | ME4600_DIO_CTRL_BIT_FUNCTION_1; | ||
182 | mask |= | ||
183 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << | ||
184 | instance->dio_idx; | ||
185 | mode &= ~mask; | ||
186 | |||
187 | if (ref == ME_REF_DIO_FIFO_LOW) { | ||
188 | mode |= | ||
189 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
190 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
191 | (instance->dio_idx * 2); | ||
192 | mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0; | ||
193 | } else if (ref == ME_REF_DIO_FIFO_HIGH) { | ||
194 | mode |= | ||
195 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
196 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
197 | (instance->dio_idx * 2); | ||
198 | mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0; | ||
199 | mode |= | ||
200 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << | ||
201 | instance->dio_idx; | ||
202 | } else { | ||
203 | PERROR | ||
204 | ("Invalid port reference specified.\n"); | ||
205 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
206 | } | ||
207 | } else if (single_config == | ||
208 | ME_SINGLE_CONFIG_DIO_BIT_PATTERN) { | ||
209 | mask = | ||
210 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
211 | ME4600_DIO_CTRL_BIT_MODE_1) << (instance-> | ||
212 | dio_idx * | ||
213 | 2); | ||
214 | mask |= | ||
215 | ME4600_DIO_CTRL_BIT_FUNCTION_0 | | ||
216 | ME4600_DIO_CTRL_BIT_FUNCTION_1; | ||
217 | mask |= | ||
218 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << | ||
219 | instance->dio_idx; | ||
220 | mode &= ~mask; | ||
221 | |||
222 | if (ref == ME_REF_DIO_FIFO_LOW) { | ||
223 | mode |= | ||
224 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
225 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
226 | (instance->dio_idx * 2); | ||
227 | } else if (ref == ME_REF_DIO_FIFO_HIGH) { | ||
228 | mode |= | ||
229 | (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
230 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
231 | (instance->dio_idx * 2); | ||
232 | mode |= | ||
233 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << | ||
234 | instance->dio_idx; | ||
235 | } else { | ||
236 | PERROR | ||
237 | ("Invalid port reference specified.\n"); | ||
238 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
239 | } | ||
240 | } else { | ||
241 | PERROR | ||
242 | ("Invalid port configuration specified.\n"); | ||
243 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
244 | } | ||
245 | } else { | ||
246 | PERROR("Invalid channel number.\n"); | ||
247 | err = ME_ERRNO_INVALID_CHANNEL; | ||
248 | } | ||
249 | |||
250 | break; | ||
251 | |||
252 | default: | ||
253 | PERROR("Invalid flags.\n"); | ||
254 | err = ME_ERRNO_INVALID_FLAGS; | ||
255 | } | ||
256 | |||
257 | if (!err) { | ||
258 | outl(mode, instance->ctrl_reg); | ||
259 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
260 | instance->reg_base, | ||
261 | instance->ctrl_reg - instance->reg_base, mode); | ||
262 | } | ||
263 | spin_unlock(instance->ctrl_reg_lock); | ||
264 | spin_unlock(&instance->subdevice_lock); | ||
265 | |||
266 | ME_SUBDEVICE_EXIT; | ||
267 | |||
268 | return err; | ||
269 | } | ||
270 | |||
271 | static int me4600_dio_io_single_read(me_subdevice_t *subdevice, | ||
272 | struct file *filep, | ||
273 | int channel, | ||
274 | int *value, int time_out, int flags) | ||
275 | { | ||
276 | me4600_dio_subdevice_t *instance; | ||
277 | int err = ME_ERRNO_SUCCESS; | ||
278 | uint32_t mode; | ||
279 | |||
280 | PDEBUG("executed.\n"); | ||
281 | |||
282 | instance = (me4600_dio_subdevice_t *) subdevice; | ||
283 | |||
284 | ME_SUBDEVICE_ENTER; | ||
285 | |||
286 | spin_lock(&instance->subdevice_lock); | ||
287 | spin_lock(instance->ctrl_reg_lock); | ||
288 | switch (flags) { | ||
289 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
290 | if ((channel >= 0) && (channel < 8)) { | ||
291 | mode = | ||
292 | inl(instance-> | ||
293 | ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | | ||
294 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
295 | (instance->dio_idx * 2)); | ||
296 | if ((mode == | ||
297 | (ME4600_DIO_CTRL_BIT_MODE_0 << | ||
298 | (instance->dio_idx * 2))) || !mode) { | ||
299 | *value = | ||
300 | inl(instance->port_reg) & (0x1 << channel); | ||
301 | } else { | ||
302 | PERROR("Port not in output or input mode.\n"); | ||
303 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
304 | } | ||
305 | } else { | ||
306 | PERROR("Invalid bit number specified.\n"); | ||
307 | err = ME_ERRNO_INVALID_CHANNEL; | ||
308 | } | ||
309 | break; | ||
310 | |||
311 | case ME_IO_SINGLE_NO_FLAGS: | ||
312 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
313 | if (channel == 0) { | ||
314 | mode = | ||
315 | inl(instance-> | ||
316 | ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | | ||
317 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
318 | (instance->dio_idx * 2)); | ||
319 | if ((mode == | ||
320 | (ME4600_DIO_CTRL_BIT_MODE_0 << | ||
321 | (instance->dio_idx * 2))) || !mode) { | ||
322 | *value = inl(instance->port_reg) & 0xFF; | ||
323 | } else { | ||
324 | PERROR("Port not in output or input mode.\n"); | ||
325 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
326 | } | ||
327 | } else { | ||
328 | PERROR("Invalid byte number specified.\n"); | ||
329 | err = ME_ERRNO_INVALID_CHANNEL; | ||
330 | } | ||
331 | break; | ||
332 | |||
333 | default: | ||
334 | PERROR("Invalid flags specified.\n"); | ||
335 | err = ME_ERRNO_INVALID_FLAGS; | ||
336 | } | ||
337 | spin_unlock(instance->ctrl_reg_lock); | ||
338 | spin_unlock(&instance->subdevice_lock); | ||
339 | |||
340 | ME_SUBDEVICE_EXIT; | ||
341 | |||
342 | return err; | ||
343 | } | ||
344 | |||
345 | static int me4600_dio_io_single_write(me_subdevice_t *subdevice, | ||
346 | struct file *filep, | ||
347 | int channel, | ||
348 | int value, int time_out, int flags) | ||
349 | { | ||
350 | me4600_dio_subdevice_t *instance; | ||
351 | int err = ME_ERRNO_SUCCESS; | ||
352 | uint32_t mode; | ||
353 | uint32_t byte; | ||
354 | |||
355 | PDEBUG("executed.\n"); | ||
356 | |||
357 | instance = (me4600_dio_subdevice_t *) subdevice; | ||
358 | |||
359 | ME_SUBDEVICE_ENTER; | ||
360 | |||
361 | spin_lock(&instance->subdevice_lock); | ||
362 | spin_lock(instance->ctrl_reg_lock); | ||
363 | switch (flags) { | ||
364 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
365 | if ((channel >= 0) && (channel < 8)) { | ||
366 | mode = | ||
367 | inl(instance-> | ||
368 | ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | | ||
369 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
370 | (instance->dio_idx * 2)); | ||
371 | |||
372 | if (mode == | ||
373 | (ME4600_DIO_CTRL_BIT_MODE_0 << | ||
374 | (instance->dio_idx * 2))) { | ||
375 | byte = inl(instance->port_reg) & 0xFF; | ||
376 | |||
377 | if (value) | ||
378 | byte |= 0x1 << channel; | ||
379 | else | ||
380 | byte &= ~(0x1 << channel); | ||
381 | |||
382 | outl(byte, instance->port_reg); | ||
383 | } else { | ||
384 | PERROR("Port not in output or input mode.\n"); | ||
385 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
386 | } | ||
387 | } else { | ||
388 | PERROR("Invalid bit number specified.\n"); | ||
389 | err = ME_ERRNO_INVALID_CHANNEL; | ||
390 | } | ||
391 | break; | ||
392 | |||
393 | case ME_IO_SINGLE_NO_FLAGS: | ||
394 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
395 | if (channel == 0) { | ||
396 | mode = | ||
397 | inl(instance-> | ||
398 | ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | | ||
399 | ME4600_DIO_CTRL_BIT_MODE_1) << | ||
400 | (instance->dio_idx * 2)); | ||
401 | |||
402 | if (mode == | ||
403 | (ME4600_DIO_CTRL_BIT_MODE_0 << | ||
404 | (instance->dio_idx * 2))) { | ||
405 | outl(value, instance->port_reg); | ||
406 | } else { | ||
407 | PERROR("Port not in output or input mode.\n"); | ||
408 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
409 | } | ||
410 | } else { | ||
411 | PERROR("Invalid byte number specified.\n"); | ||
412 | err = ME_ERRNO_INVALID_CHANNEL; | ||
413 | } | ||
414 | break; | ||
415 | |||
416 | default: | ||
417 | PERROR("Invalid flags specified.\n"); | ||
418 | err = ME_ERRNO_INVALID_FLAGS; | ||
419 | } | ||
420 | spin_unlock(instance->ctrl_reg_lock); | ||
421 | spin_unlock(&instance->subdevice_lock); | ||
422 | |||
423 | ME_SUBDEVICE_EXIT; | ||
424 | |||
425 | return err; | ||
426 | } | ||
427 | |||
428 | static int me4600_dio_query_number_channels(me_subdevice_t *subdevice, | ||
429 | int *number) | ||
430 | { | ||
431 | PDEBUG("executed.\n"); | ||
432 | *number = 8; | ||
433 | return ME_ERRNO_SUCCESS; | ||
434 | } | ||
435 | |||
436 | static int me4600_dio_query_subdevice_type(me_subdevice_t *subdevice, | ||
437 | int *type, int *subtype) | ||
438 | { | ||
439 | PDEBUG("executed.\n"); | ||
440 | *type = ME_TYPE_DIO; | ||
441 | *subtype = ME_SUBTYPE_SINGLE; | ||
442 | return ME_ERRNO_SUCCESS; | ||
443 | } | ||
444 | |||
445 | static int me4600_dio_query_subdevice_caps(me_subdevice_t *subdevice, | ||
446 | int *caps) | ||
447 | { | ||
448 | PDEBUG("executed.\n"); | ||
449 | *caps = ME_CAPS_DIO_DIR_BYTE; | ||
450 | return ME_ERRNO_SUCCESS; | ||
451 | } | ||
452 | |||
453 | me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base, | ||
454 | unsigned int dio_idx, | ||
455 | spinlock_t *ctrl_reg_lock) | ||
456 | { | ||
457 | me4600_dio_subdevice_t *subdevice; | ||
458 | int err; | ||
459 | |||
460 | PDEBUG("executed.\n"); | ||
461 | |||
462 | /* Allocate memory for subdevice instance */ | ||
463 | subdevice = kmalloc(sizeof(me4600_dio_subdevice_t), GFP_KERNEL); | ||
464 | |||
465 | if (!subdevice) { | ||
466 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
467 | return NULL; | ||
468 | } | ||
469 | |||
470 | memset(subdevice, 0, sizeof(me4600_dio_subdevice_t)); | ||
471 | |||
472 | /* Initialize subdevice base class */ | ||
473 | err = me_subdevice_init(&subdevice->base); | ||
474 | |||
475 | if (err) { | ||
476 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
477 | kfree(subdevice); | ||
478 | return NULL; | ||
479 | } | ||
480 | // Initialize spin locks. | ||
481 | spin_lock_init(&subdevice->subdevice_lock); | ||
482 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
483 | |||
484 | /* Save digital i/o index */ | ||
485 | subdevice->dio_idx = dio_idx; | ||
486 | |||
487 | /* Save the subdevice index */ | ||
488 | subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG; | ||
489 | subdevice->port_reg = reg_base + ME4600_DIO_PORT_REG + (dio_idx * 4); | ||
490 | #ifdef MEDEBUG_DEBUG_REG | ||
491 | subdevice->reg_base = reg_base; | ||
492 | #endif | ||
493 | |||
494 | /* Overload base class methods. */ | ||
495 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
496 | me4600_dio_io_reset_subdevice; | ||
497 | subdevice->base.me_subdevice_io_single_config = | ||
498 | me4600_dio_io_single_config; | ||
499 | subdevice->base.me_subdevice_io_single_read = me4600_dio_io_single_read; | ||
500 | subdevice->base.me_subdevice_io_single_write = | ||
501 | me4600_dio_io_single_write; | ||
502 | subdevice->base.me_subdevice_query_number_channels = | ||
503 | me4600_dio_query_number_channels; | ||
504 | subdevice->base.me_subdevice_query_subdevice_type = | ||
505 | me4600_dio_query_subdevice_type; | ||
506 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
507 | me4600_dio_query_subdevice_caps; | ||
508 | |||
509 | return subdevice; | ||
510 | } | ||
diff --git a/drivers/staging/meilhaus/me4600_dio.h b/drivers/staging/meilhaus/me4600_dio.h deleted file mode 100644 index 4625ba91f609..000000000000 --- a/drivers/staging/meilhaus/me4600_dio.h +++ /dev/null | |||
@@ -1,69 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_dio.h | ||
3 | * | ||
4 | * @brief ME-4000 digital input/output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_DIO_H_ | ||
28 | #define _ME4600_DIO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me4600_dio_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | unsigned int dio_idx; /**< The index of the digital i/o on the device. */ | ||
45 | |||
46 | /* Registers */ | ||
47 | unsigned long port_reg; /**< Register holding the port status. */ | ||
48 | unsigned long ctrl_reg; /**< Register to configure the port direction. */ | ||
49 | #ifdef MEDEBUG_DEBUG_REG | ||
50 | unsigned long reg_base; | ||
51 | #endif | ||
52 | } me4600_dio_subdevice_t; | ||
53 | |||
54 | /** | ||
55 | * @brief The constructor to generate a ME-4000 digital input/ouput subdevice instance. | ||
56 | * | ||
57 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
58 | * @param dio_idx The index of the digital i/o port on the device. | ||
59 | * @param ctrl_reg_lock Spin lock protecting the control register. | ||
60 | * | ||
61 | * @return Pointer to new instance on success.\n | ||
62 | * NULL on error. | ||
63 | */ | ||
64 | me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base, | ||
65 | unsigned int dio_idx, | ||
66 | spinlock_t * ctrl_reg_lock); | ||
67 | |||
68 | #endif | ||
69 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_dio_reg.h b/drivers/staging/meilhaus/me4600_dio_reg.h deleted file mode 100644 index 7a4016a80fd2..000000000000 --- a/drivers/staging/meilhaus/me4600_dio_reg.h +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_dio_reg.h | ||
3 | * | ||
4 | * @brief ME-4000 digital input/output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_DIO_REG_H_ | ||
28 | #define _ME4600_DIO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME4600_DIO_PORT_0_REG 0xA0 /**< Port 0 register. */ | ||
33 | #define ME4600_DIO_PORT_1_REG 0xA4 /**< Port 1 register. */ | ||
34 | #define ME4600_DIO_PORT_2_REG 0xA8 /**< Port 2 register. */ | ||
35 | #define ME4600_DIO_PORT_3_REG 0xAC /**< Port 3 register. */ | ||
36 | |||
37 | #define ME4600_DIO_DIR_REG 0xB0 /**< Direction register. */ | ||
38 | #define ME4600_DIO_PORT_REG ME4600_DIO_PORT_0_REG /**< Base for port's register. */ | ||
39 | |||
40 | #define ME4600_DIO_CTRL_REG 0xB8 /**< Control register. */ | ||
41 | /** Port A - DO */ | ||
42 | #define ME4600_DIO_CTRL_BIT_MODE_0 0x0001 | ||
43 | #define ME4600_DIO_CTRL_BIT_MODE_1 0x0002 | ||
44 | /** Port B - DI */ | ||
45 | #define ME4600_DIO_CTRL_BIT_MODE_2 0x0004 | ||
46 | #define ME4600_DIO_CTRL_BIT_MODE_3 0x0008 | ||
47 | /** Port C - DIO */ | ||
48 | #define ME4600_DIO_CTRL_BIT_MODE_4 0x0010 | ||
49 | #define ME4600_DIO_CTRL_BIT_MODE_5 0x0020 | ||
50 | /** Port D - DIO */ | ||
51 | #define ME4600_DIO_CTRL_BIT_MODE_6 0x0040 | ||
52 | #define ME4600_DIO_CTRL_BIT_MODE_7 0x0080 | ||
53 | |||
54 | #define ME4600_DIO_CTRL_BIT_FUNCTION_0 0x0100 | ||
55 | #define ME4600_DIO_CTRL_BIT_FUNCTION_1 0x0200 | ||
56 | |||
57 | #define ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 0x0400 | ||
58 | #define ME4600_DIO_CTRL_BIT_FIFO_HIGH_1 0x0800 | ||
59 | #define ME4600_DIO_CTRL_BIT_FIFO_HIGH_2 0x1000 | ||
60 | #define ME4600_DIO_CTRL_BIT_FIFO_HIGH_3 0x2000 | ||
61 | |||
62 | #endif | ||
63 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_do.c b/drivers/staging/meilhaus/me4600_do.c deleted file mode 100644 index 39510f3e6e67..000000000000 --- a/drivers/staging/meilhaus/me4600_do.c +++ /dev/null | |||
@@ -1,433 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_do.c | ||
3 | * | ||
4 | * @brief ME-4000 digital output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me4600_dio_reg.h" | ||
48 | #include "me4600_do.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me4600_do_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | me4600_do_subdevice_t *instance; | ||
62 | uint32_t mode; | ||
63 | |||
64 | PDEBUG("executed.\n"); | ||
65 | |||
66 | instance = (me4600_do_subdevice_t *) subdevice; | ||
67 | |||
68 | if (flags) { | ||
69 | PERROR("Invalid flag specified.\n"); | ||
70 | return ME_ERRNO_INVALID_FLAGS; | ||
71 | } | ||
72 | |||
73 | ME_SUBDEVICE_ENTER; | ||
74 | |||
75 | /* Set port to output mode */ | ||
76 | spin_lock(&instance->subdevice_lock); | ||
77 | spin_lock(instance->ctrl_reg_lock); | ||
78 | mode = inl(instance->ctrl_reg); | ||
79 | mode &= ~ME4600_DIO_CTRL_BIT_MODE_1; //0xFFFD | ||
80 | mode |= ME4600_DIO_CTRL_BIT_MODE_0; //0x1 | ||
81 | outl(mode, instance->ctrl_reg); | ||
82 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
83 | instance->ctrl_reg - instance->reg_base, mode); | ||
84 | spin_unlock(instance->ctrl_reg_lock); | ||
85 | |||
86 | outl(0, instance->port_reg); | ||
87 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
88 | instance->port_reg - instance->reg_base, 0); | ||
89 | spin_unlock(&instance->subdevice_lock); | ||
90 | |||
91 | ME_SUBDEVICE_EXIT; | ||
92 | |||
93 | return ME_ERRNO_SUCCESS; | ||
94 | } | ||
95 | |||
96 | static int me4600_do_io_single_config(me_subdevice_t *subdevice, | ||
97 | struct file *filep, | ||
98 | int channel, | ||
99 | int single_config, | ||
100 | int ref, | ||
101 | int trig_chan, | ||
102 | int trig_type, int trig_edge, int flags) | ||
103 | { | ||
104 | me4600_do_subdevice_t *instance; | ||
105 | int err = ME_ERRNO_SUCCESS; | ||
106 | uint32_t mode; | ||
107 | int size = | ||
108 | flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE | ||
109 | | ME_IO_SINGLE_CONFIG_DIO_WORD | | ||
110 | ME_IO_SINGLE_CONFIG_DIO_DWORD); | ||
111 | |||
112 | PDEBUG("executed.\n"); | ||
113 | |||
114 | instance = (me4600_do_subdevice_t *) subdevice; | ||
115 | |||
116 | ME_SUBDEVICE_ENTER; | ||
117 | |||
118 | spin_lock(&instance->subdevice_lock); | ||
119 | spin_lock(instance->ctrl_reg_lock); | ||
120 | mode = inl(instance->ctrl_reg); | ||
121 | |||
122 | switch (size) { | ||
123 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
124 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
125 | if (channel == 0) { | ||
126 | if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
127 | mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 | | ||
128 | ME4600_DIO_CTRL_BIT_MODE_1); | ||
129 | mode |= (ME4600_DIO_CTRL_BIT_MODE_0); | ||
130 | } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) { | ||
131 | mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 | | ||
132 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
133 | ME4600_DIO_CTRL_BIT_FUNCTION_0 | | ||
134 | ME4600_DIO_CTRL_BIT_FUNCTION_1 | | ||
135 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); | ||
136 | |||
137 | if (ref == ME_REF_DIO_FIFO_LOW) { | ||
138 | mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
139 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
140 | ME4600_DIO_CTRL_BIT_FUNCTION_1); | ||
141 | } else if (ref == ME_REF_DIO_FIFO_HIGH) { | ||
142 | mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
143 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
144 | ME4600_DIO_CTRL_BIT_FUNCTION_1 | ||
145 | | | ||
146 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); | ||
147 | } else { | ||
148 | PERROR | ||
149 | ("Invalid port reference specified.\n"); | ||
150 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
151 | } | ||
152 | } else if (single_config == | ||
153 | ME_SINGLE_CONFIG_DIO_DEMUX32) { | ||
154 | mode &= | ||
155 | ~(ME4600_DIO_CTRL_BIT_MODE_0 | | ||
156 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
157 | ME4600_DIO_CTRL_BIT_FUNCTION_0 | | ||
158 | ME4600_DIO_CTRL_BIT_FUNCTION_1 | | ||
159 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); | ||
160 | |||
161 | if (ref == ME_REF_DIO_FIFO_LOW) { | ||
162 | mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
163 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
164 | ME4600_DIO_CTRL_BIT_FUNCTION_0); | ||
165 | } else if (ref == ME_REF_DIO_FIFO_HIGH) { | ||
166 | mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
167 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
168 | ME4600_DIO_CTRL_BIT_FUNCTION_0 | ||
169 | | | ||
170 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); | ||
171 | } else { | ||
172 | PERROR | ||
173 | ("Invalid port reference specified.\n"); | ||
174 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
175 | } | ||
176 | } else if (single_config == | ||
177 | ME_SINGLE_CONFIG_DIO_BIT_PATTERN) { | ||
178 | mode &= | ||
179 | ~(ME4600_DIO_CTRL_BIT_MODE_0 | | ||
180 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
181 | ME4600_DIO_CTRL_BIT_FUNCTION_0 | | ||
182 | ME4600_DIO_CTRL_BIT_FUNCTION_1 | | ||
183 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); | ||
184 | |||
185 | if (ref == ME_REF_DIO_FIFO_LOW) { | ||
186 | mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
187 | ME4600_DIO_CTRL_BIT_MODE_1); | ||
188 | } else if (ref == ME_REF_DIO_FIFO_HIGH) { | ||
189 | mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
190 | ME4600_DIO_CTRL_BIT_MODE_1 | | ||
191 | ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); | ||
192 | } else { | ||
193 | PERROR | ||
194 | ("Invalid port reference specified.\n"); | ||
195 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
196 | } | ||
197 | } else { | ||
198 | PERROR("Invalid port direction specified.\n"); | ||
199 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
200 | } | ||
201 | } else { | ||
202 | PERROR("Invalid channel number.\n"); | ||
203 | err = ME_ERRNO_INVALID_CHANNEL; | ||
204 | } | ||
205 | |||
206 | break; | ||
207 | |||
208 | default: | ||
209 | PERROR("Invalid flags specified.\n"); | ||
210 | err = ME_ERRNO_INVALID_FLAGS; | ||
211 | } | ||
212 | |||
213 | if (!err) { | ||
214 | outl(mode, instance->ctrl_reg); | ||
215 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
216 | instance->reg_base, | ||
217 | instance->ctrl_reg - instance->reg_base, mode); | ||
218 | } | ||
219 | spin_unlock(instance->ctrl_reg_lock); | ||
220 | spin_unlock(&instance->subdevice_lock); | ||
221 | |||
222 | ME_SUBDEVICE_EXIT; | ||
223 | |||
224 | return err; | ||
225 | } | ||
226 | |||
227 | static int me4600_do_io_single_read(me_subdevice_t *subdevice, | ||
228 | struct file *filep, | ||
229 | int channel, | ||
230 | int *value, int time_out, int flags) | ||
231 | { | ||
232 | me4600_do_subdevice_t *instance; | ||
233 | int err = ME_ERRNO_SUCCESS; | ||
234 | uint32_t mode; | ||
235 | |||
236 | PDEBUG("executed.\n"); | ||
237 | |||
238 | instance = (me4600_do_subdevice_t *) subdevice; | ||
239 | |||
240 | ME_SUBDEVICE_ENTER; | ||
241 | |||
242 | spin_lock(&instance->subdevice_lock); | ||
243 | spin_lock(instance->ctrl_reg_lock); | ||
244 | mode = | ||
245 | inl(instance-> | ||
246 | ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
247 | ME4600_DIO_CTRL_BIT_MODE_1); | ||
248 | |||
249 | if (mode == ME4600_DIO_CTRL_BIT_MODE_0) { | ||
250 | switch (flags) { | ||
251 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
252 | if ((channel >= 0) && (channel < 8)) { | ||
253 | *value = | ||
254 | inl(instance->port_reg) & (0x1 << channel); | ||
255 | } else { | ||
256 | PERROR("Invalid bit number specified.\n"); | ||
257 | err = ME_ERRNO_INVALID_CHANNEL; | ||
258 | } | ||
259 | break; | ||
260 | |||
261 | case ME_IO_SINGLE_NO_FLAGS: | ||
262 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
263 | if (channel == 0) { | ||
264 | *value = inl(instance->port_reg) & 0xFF; | ||
265 | } else { | ||
266 | PERROR("Invalid byte number specified.\n"); | ||
267 | err = ME_ERRNO_INVALID_CHANNEL; | ||
268 | } | ||
269 | break; | ||
270 | |||
271 | default: | ||
272 | PERROR("Invalid flags specified.\n"); | ||
273 | err = ME_ERRNO_INVALID_FLAGS; | ||
274 | } | ||
275 | } else { | ||
276 | PERROR("Port not in output mode.\n"); | ||
277 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
278 | } | ||
279 | spin_unlock(instance->ctrl_reg_lock); | ||
280 | spin_unlock(&instance->subdevice_lock); | ||
281 | |||
282 | ME_SUBDEVICE_EXIT; | ||
283 | |||
284 | return err; | ||
285 | } | ||
286 | |||
287 | static int me4600_do_io_single_write(me_subdevice_t *subdevice, | ||
288 | struct file *filep, | ||
289 | int channel, | ||
290 | int value, int time_out, int flags) | ||
291 | { | ||
292 | me4600_do_subdevice_t *instance; | ||
293 | int err = ME_ERRNO_SUCCESS; | ||
294 | uint32_t byte; | ||
295 | uint32_t mode; | ||
296 | |||
297 | PDEBUG("executed.\n"); | ||
298 | |||
299 | instance = (me4600_do_subdevice_t *) subdevice; | ||
300 | |||
301 | ME_SUBDEVICE_ENTER; | ||
302 | |||
303 | spin_lock(&instance->subdevice_lock); | ||
304 | spin_lock(instance->ctrl_reg_lock); | ||
305 | mode = | ||
306 | inl(instance-> | ||
307 | ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 | | ||
308 | ME4600_DIO_CTRL_BIT_MODE_1); | ||
309 | |||
310 | if (mode == ME4600_DIO_CTRL_BIT_MODE_0) { | ||
311 | switch (flags) { | ||
312 | |||
313 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
314 | if ((channel >= 0) && (channel < 8)) { | ||
315 | byte = inl(instance->port_reg) & 0xFF; | ||
316 | |||
317 | if (value) | ||
318 | byte |= 0x1 << channel; | ||
319 | else | ||
320 | byte &= ~(0x1 << channel); | ||
321 | |||
322 | outl(byte, instance->port_reg); | ||
323 | } else { | ||
324 | PERROR("Invalid bit number specified.\n"); | ||
325 | err = ME_ERRNO_INVALID_CHANNEL; | ||
326 | } | ||
327 | break; | ||
328 | |||
329 | case ME_IO_SINGLE_NO_FLAGS: | ||
330 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
331 | if (channel == 0) { | ||
332 | outl(value, instance->port_reg); | ||
333 | } else { | ||
334 | PERROR("Invalid byte number specified.\n"); | ||
335 | err = ME_ERRNO_INVALID_CHANNEL; | ||
336 | } | ||
337 | break; | ||
338 | |||
339 | default: | ||
340 | PERROR("Invalid flags specified.\n"); | ||
341 | err = ME_ERRNO_INVALID_FLAGS; | ||
342 | } | ||
343 | } else { | ||
344 | PERROR("Port not in output mode.\n"); | ||
345 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
346 | } | ||
347 | spin_unlock(instance->ctrl_reg_lock); | ||
348 | spin_unlock(&instance->subdevice_lock); | ||
349 | |||
350 | ME_SUBDEVICE_EXIT; | ||
351 | |||
352 | return err; | ||
353 | } | ||
354 | |||
355 | static int me4600_do_query_number_channels(me_subdevice_t *subdevice, | ||
356 | int *number) | ||
357 | { | ||
358 | PDEBUG("executed.\n"); | ||
359 | *number = 8; | ||
360 | return ME_ERRNO_SUCCESS; | ||
361 | } | ||
362 | |||
363 | static int me4600_do_query_subdevice_type(me_subdevice_t *subdevice, | ||
364 | int *type, int *subtype) | ||
365 | { | ||
366 | PDEBUG("executed.\n"); | ||
367 | *type = ME_TYPE_DO; | ||
368 | *subtype = ME_SUBTYPE_SINGLE; | ||
369 | return ME_ERRNO_SUCCESS; | ||
370 | } | ||
371 | |||
372 | static int me4600_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
373 | { | ||
374 | PDEBUG("executed.\n"); | ||
375 | *caps = 0; | ||
376 | return ME_ERRNO_SUCCESS; | ||
377 | } | ||
378 | |||
379 | me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base, | ||
380 | spinlock_t *ctrl_reg_lock) | ||
381 | { | ||
382 | me4600_do_subdevice_t *subdevice; | ||
383 | int err; | ||
384 | |||
385 | PDEBUG("executed.\n"); | ||
386 | |||
387 | /* Allocate memory for subdevice instance */ | ||
388 | subdevice = kmalloc(sizeof(me4600_do_subdevice_t), GFP_KERNEL); | ||
389 | |||
390 | if (!subdevice) { | ||
391 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
392 | return NULL; | ||
393 | } | ||
394 | |||
395 | memset(subdevice, 0, sizeof(me4600_do_subdevice_t)); | ||
396 | |||
397 | /* Initialize subdevice base class */ | ||
398 | err = me_subdevice_init(&subdevice->base); | ||
399 | |||
400 | if (err) { | ||
401 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
402 | kfree(subdevice); | ||
403 | return NULL; | ||
404 | } | ||
405 | // Initialize spin locks. | ||
406 | spin_lock_init(&subdevice->subdevice_lock); | ||
407 | |||
408 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
409 | |||
410 | /* Save the subdevice index */ | ||
411 | subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG; | ||
412 | subdevice->port_reg = reg_base + ME4600_DIO_PORT_0_REG; | ||
413 | #ifdef MEDEBUG_DEBUG_REG | ||
414 | subdevice->reg_base = reg_base; | ||
415 | #endif | ||
416 | |||
417 | /* Overload base class methods. */ | ||
418 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
419 | me4600_do_io_reset_subdevice; | ||
420 | subdevice->base.me_subdevice_io_single_config = | ||
421 | me4600_do_io_single_config; | ||
422 | subdevice->base.me_subdevice_io_single_read = me4600_do_io_single_read; | ||
423 | subdevice->base.me_subdevice_io_single_write = | ||
424 | me4600_do_io_single_write; | ||
425 | subdevice->base.me_subdevice_query_number_channels = | ||
426 | me4600_do_query_number_channels; | ||
427 | subdevice->base.me_subdevice_query_subdevice_type = | ||
428 | me4600_do_query_subdevice_type; | ||
429 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
430 | me4600_do_query_subdevice_caps; | ||
431 | |||
432 | return subdevice; | ||
433 | } | ||
diff --git a/drivers/staging/meilhaus/me4600_do.h b/drivers/staging/meilhaus/me4600_do.h deleted file mode 100644 index e8385648e925..000000000000 --- a/drivers/staging/meilhaus/me4600_do.h +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_do.h | ||
3 | * | ||
4 | * @brief ME-4000 digital output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_DO_H_ | ||
28 | #define _ME4600_DO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me4600_do_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | |||
45 | unsigned long port_reg; /**< Register holding the port status. */ | ||
46 | unsigned long ctrl_reg; /**< Register to configure the port direction. */ | ||
47 | #ifdef MEDEBUG_DEBUG_REG | ||
48 | unsigned long reg_base; | ||
49 | #endif | ||
50 | } me4600_do_subdevice_t; | ||
51 | |||
52 | /** | ||
53 | * @brief The constructor to generate a ME-4000 digital output subdevice instance. | ||
54 | * | ||
55 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
56 | * @param ctrl_reg_lock Spin lock protecting the control register. | ||
57 | * | ||
58 | * @return Pointer to new instance on success.\n | ||
59 | * NULL on error. | ||
60 | */ | ||
61 | me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base, | ||
62 | spinlock_t * ctrl_reg_lock); | ||
63 | |||
64 | #endif | ||
65 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_ext_irq.c b/drivers/staging/meilhaus/me4600_ext_irq.c deleted file mode 100644 index cfb4adbd41ab..000000000000 --- a/drivers/staging/meilhaus/me4600_ext_irq.c +++ /dev/null | |||
@@ -1,457 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ext_irq.c | ||
3 | * | ||
4 | * @brief ME-4000 external interrupt subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/io.h> | ||
41 | #include <linux/types.h> | ||
42 | |||
43 | #include "medefines.h" | ||
44 | #include "meinternal.h" | ||
45 | #include "meerror.h" | ||
46 | |||
47 | #include "medebug.h" | ||
48 | #include "meids.h" | ||
49 | #include "me4600_reg.h" | ||
50 | #include "me4600_ai_reg.h" | ||
51 | #include "me4600_ext_irq_reg.h" | ||
52 | #include "me4600_ext_irq.h" | ||
53 | |||
54 | /* | ||
55 | * Defines | ||
56 | */ | ||
57 | |||
58 | /* | ||
59 | * Functions | ||
60 | */ | ||
61 | |||
62 | static int me4600_ext_irq_io_irq_start(me_subdevice_t *subdevice, | ||
63 | struct file *filep, | ||
64 | int channel, | ||
65 | int irq_source, | ||
66 | int irq_edge, int irq_arg, int flags) | ||
67 | { | ||
68 | me4600_ext_irq_subdevice_t *instance; | ||
69 | int err = ME_ERRNO_SUCCESS; | ||
70 | unsigned long cpu_flags; | ||
71 | uint32_t tmp; | ||
72 | |||
73 | PDEBUG("executed.\n"); | ||
74 | |||
75 | instance = (me4600_ext_irq_subdevice_t *) subdevice; | ||
76 | |||
77 | if (flags & ~ME_IO_IRQ_START_DIO_BIT) { | ||
78 | PERROR("Invalid flag specified.\n"); | ||
79 | return ME_ERRNO_INVALID_FLAGS; | ||
80 | } | ||
81 | |||
82 | if ((irq_edge != ME_IRQ_EDGE_RISING) | ||
83 | && (irq_edge != ME_IRQ_EDGE_FALLING) | ||
84 | && (irq_edge != ME_IRQ_EDGE_ANY) | ||
85 | ) { | ||
86 | PERROR("Invalid irq edge specified.\n"); | ||
87 | return ME_ERRNO_INVALID_IRQ_EDGE; | ||
88 | } | ||
89 | |||
90 | if (irq_source != ME_IRQ_SOURCE_DIO_LINE) { | ||
91 | PERROR("Invalid irq source specified.\n"); | ||
92 | return ME_ERRNO_INVALID_IRQ_SOURCE; | ||
93 | } | ||
94 | |||
95 | if (channel) { | ||
96 | PERROR("Invalid channel specified.\n"); | ||
97 | return ME_ERRNO_INVALID_CHANNEL; | ||
98 | } | ||
99 | |||
100 | ME_SUBDEVICE_ENTER; | ||
101 | |||
102 | spin_lock(&instance->subdevice_lock); | ||
103 | tmp = 0x0; //inl(instance->ext_irq_config_reg); | ||
104 | |||
105 | if (irq_edge == ME_IRQ_EDGE_RISING) { | ||
106 | //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK; | ||
107 | //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_RISING; | ||
108 | } else if (irq_edge == ME_IRQ_EDGE_FALLING) { | ||
109 | //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK; | ||
110 | //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_FALLING; | ||
111 | tmp = ME4600_EXT_IRQ_CONFIG_MASK_FALLING; | ||
112 | } else if (irq_edge == ME_IRQ_EDGE_ANY) { | ||
113 | //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK; | ||
114 | //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_ANY; | ||
115 | tmp = ME4600_EXT_IRQ_CONFIG_MASK_ANY; | ||
116 | } | ||
117 | |||
118 | outl(tmp, instance->ext_irq_config_reg); | ||
119 | PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
120 | instance->reg_base, | ||
121 | instance->ext_irq_config_reg - instance->reg_base, tmp); | ||
122 | |||
123 | spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); | ||
124 | tmp = inl(instance->ctrl_reg); | ||
125 | tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); | ||
126 | tmp |= ME4600_AI_CTRL_BIT_EX_IRQ; | ||
127 | outl(tmp, instance->ctrl_reg); | ||
128 | spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); | ||
129 | instance->rised = 0; | ||
130 | spin_unlock(&instance->subdevice_lock); | ||
131 | |||
132 | ME_SUBDEVICE_EXIT; | ||
133 | |||
134 | return err; | ||
135 | } | ||
136 | |||
137 | static int me4600_ext_irq_io_irq_wait(me_subdevice_t *subdevice, | ||
138 | struct file *filep, | ||
139 | int channel, | ||
140 | int *irq_count, | ||
141 | int *value, int time_out, int flags) | ||
142 | { | ||
143 | me4600_ext_irq_subdevice_t *instance; | ||
144 | int err = ME_ERRNO_SUCCESS; | ||
145 | long t = 0; | ||
146 | unsigned long cpu_flags; | ||
147 | |||
148 | PDEBUG("executed.\n"); | ||
149 | |||
150 | instance = (me4600_ext_irq_subdevice_t *) subdevice; | ||
151 | |||
152 | if (flags) { | ||
153 | PERROR("Invalid flag specified.\n"); | ||
154 | return ME_ERRNO_INVALID_FLAGS; | ||
155 | } | ||
156 | |||
157 | if (channel) { | ||
158 | PERROR("Invalid channel specified.\n"); | ||
159 | return ME_ERRNO_INVALID_CHANNEL; | ||
160 | } | ||
161 | |||
162 | if (time_out < 0) { | ||
163 | PERROR("Invalid time_out specified.\n"); | ||
164 | return ME_ERRNO_INVALID_TIMEOUT; | ||
165 | } | ||
166 | |||
167 | if (time_out) { | ||
168 | t = (time_out * HZ) / 1000; | ||
169 | |||
170 | if (t == 0) | ||
171 | t = 1; | ||
172 | } | ||
173 | |||
174 | ME_SUBDEVICE_ENTER; | ||
175 | |||
176 | if (instance->rised <= 0) { | ||
177 | instance->rised = 0; | ||
178 | if (time_out) { | ||
179 | t = wait_event_interruptible_timeout(instance-> | ||
180 | wait_queue, | ||
181 | (instance->rised != | ||
182 | 0), t); | ||
183 | |||
184 | if (t == 0) { | ||
185 | PERROR | ||
186 | ("Wait on external interrupt timed out.\n"); | ||
187 | err = ME_ERRNO_TIMEOUT; | ||
188 | } | ||
189 | } else { | ||
190 | wait_event_interruptible(instance->wait_queue, | ||
191 | (instance->rised != 0)); | ||
192 | } | ||
193 | |||
194 | if (instance->rised < 0) { | ||
195 | PERROR("Wait on interrupt aborted by user.\n"); | ||
196 | err = ME_ERRNO_CANCELLED; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | if (signal_pending(current)) { | ||
201 | PERROR("Wait on external interrupt aborted by signal.\n"); | ||
202 | err = ME_ERRNO_SIGNAL; | ||
203 | } | ||
204 | |||
205 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
206 | instance->rised = 0; | ||
207 | *irq_count = instance->count; | ||
208 | *value = instance->value; | ||
209 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
210 | |||
211 | ME_SUBDEVICE_EXIT; | ||
212 | |||
213 | return err; | ||
214 | } | ||
215 | |||
216 | static int me4600_ext_irq_io_irq_stop(me_subdevice_t *subdevice, | ||
217 | struct file *filep, | ||
218 | int channel, int flags) | ||
219 | { | ||
220 | me4600_ext_irq_subdevice_t *instance; | ||
221 | int err = ME_ERRNO_SUCCESS; | ||
222 | unsigned long cpu_flags; | ||
223 | uint32_t tmp; | ||
224 | |||
225 | PDEBUG("executed.\n"); | ||
226 | |||
227 | instance = (me4600_ext_irq_subdevice_t *) subdevice; | ||
228 | |||
229 | if (flags) { | ||
230 | PERROR("Invalid flag specified.\n"); | ||
231 | return ME_ERRNO_INVALID_FLAGS; | ||
232 | } | ||
233 | |||
234 | if (channel) { | ||
235 | PERROR("Invalid channel specified.\n"); | ||
236 | return ME_ERRNO_INVALID_CHANNEL; | ||
237 | } | ||
238 | |||
239 | ME_SUBDEVICE_ENTER; | ||
240 | |||
241 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
242 | spin_lock(instance->ctrl_reg_lock); | ||
243 | tmp = inl(instance->ctrl_reg); | ||
244 | tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); | ||
245 | outl(tmp, instance->ctrl_reg); | ||
246 | PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
247 | instance->ctrl_reg - instance->reg_base, tmp); | ||
248 | spin_unlock(instance->ctrl_reg_lock); | ||
249 | instance->rised = -1; | ||
250 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
251 | wake_up_interruptible_all(&instance->wait_queue); | ||
252 | |||
253 | ME_SUBDEVICE_EXIT; | ||
254 | |||
255 | return err; | ||
256 | } | ||
257 | |||
258 | static int me4600_ext_irq_io_reset_subdevice(me_subdevice_t *subdevice, | ||
259 | struct file *filep, int flags) | ||
260 | { | ||
261 | me4600_ext_irq_subdevice_t *instance; | ||
262 | unsigned long cpu_flags; | ||
263 | uint32_t tmp; | ||
264 | |||
265 | PDEBUG("executed.\n"); | ||
266 | |||
267 | instance = (me4600_ext_irq_subdevice_t *) subdevice; | ||
268 | |||
269 | if (flags) { | ||
270 | PERROR("Invalid flag specified.\n"); | ||
271 | return ME_ERRNO_INVALID_FLAGS; | ||
272 | } | ||
273 | |||
274 | ME_SUBDEVICE_ENTER; | ||
275 | |||
276 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
277 | spin_lock(instance->ctrl_reg_lock); | ||
278 | tmp = inl(instance->ctrl_reg); | ||
279 | tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); | ||
280 | outl(tmp, instance->ctrl_reg); | ||
281 | PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
282 | instance->ctrl_reg - instance->reg_base, tmp); | ||
283 | spin_unlock(instance->ctrl_reg_lock); | ||
284 | instance->rised = -1; | ||
285 | instance->count = 0; | ||
286 | outl(ME4600_EXT_IRQ_CONFIG_MASK_ANY, instance->ext_irq_config_reg); | ||
287 | PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
288 | instance->reg_base, | ||
289 | instance->ext_irq_config_reg - instance->reg_base, | ||
290 | ME4600_EXT_IRQ_CONFIG_MASK_ANY); | ||
291 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
292 | wake_up_interruptible_all(&instance->wait_queue); | ||
293 | |||
294 | ME_SUBDEVICE_EXIT; | ||
295 | |||
296 | return ME_ERRNO_SUCCESS; | ||
297 | } | ||
298 | |||
299 | static void me4600_ext_irq_destructor(struct me_subdevice *subdevice) | ||
300 | { | ||
301 | me4600_ext_irq_subdevice_t *instance; | ||
302 | |||
303 | PDEBUG("executed.\n"); | ||
304 | instance = (me4600_ext_irq_subdevice_t *) subdevice; | ||
305 | me_subdevice_deinit(&instance->base); | ||
306 | free_irq(instance->irq, instance); | ||
307 | kfree(instance); | ||
308 | } | ||
309 | |||
310 | static int me4600_ext_irq_query_number_channels(me_subdevice_t *subdevice, | ||
311 | int *number) | ||
312 | { | ||
313 | PDEBUG("executed.\n"); | ||
314 | *number = 1; | ||
315 | return ME_ERRNO_SUCCESS; | ||
316 | } | ||
317 | |||
318 | static int me4600_ext_irq_query_subdevice_type(me_subdevice_t *subdevice, | ||
319 | int *type, int *subtype) | ||
320 | { | ||
321 | PDEBUG("executed.\n"); | ||
322 | *type = ME_TYPE_EXT_IRQ; | ||
323 | *subtype = ME_SUBTYPE_SINGLE; | ||
324 | return ME_ERRNO_SUCCESS; | ||
325 | } | ||
326 | |||
327 | static int me4600_ext_irq_query_subdevice_caps(me_subdevice_t *subdevice, | ||
328 | int *caps) | ||
329 | { | ||
330 | PDEBUG("executed.\n"); | ||
331 | *caps = | ||
332 | ME_CAPS_EXT_IRQ_EDGE_RISING | ME_CAPS_EXT_IRQ_EDGE_FALLING | | ||
333 | ME_CAPS_EXT_IRQ_EDGE_ANY; | ||
334 | return ME_ERRNO_SUCCESS; | ||
335 | } | ||
336 | |||
337 | static irqreturn_t me4600_ext_irq_isr(int irq, void *dev_id) | ||
338 | { | ||
339 | me4600_ext_irq_subdevice_t *instance; | ||
340 | uint32_t ctrl; | ||
341 | uint32_t irq_status; | ||
342 | |||
343 | instance = (me4600_ext_irq_subdevice_t *) dev_id; | ||
344 | |||
345 | if (irq != instance->irq) { | ||
346 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
347 | return IRQ_NONE; | ||
348 | } | ||
349 | |||
350 | irq_status = inl(instance->irq_status_reg); | ||
351 | if (!(irq_status & ME4600_IRQ_STATUS_BIT_EX)) { | ||
352 | PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n", | ||
353 | jiffies, __func__, irq_status); | ||
354 | return IRQ_NONE; | ||
355 | } | ||
356 | |||
357 | PDEBUG("executed.\n"); | ||
358 | |||
359 | spin_lock(&instance->subdevice_lock); | ||
360 | instance->rised = 1; | ||
361 | instance->value = inl(instance->ext_irq_value_reg); | ||
362 | instance->count++; | ||
363 | |||
364 | spin_lock(instance->ctrl_reg_lock); | ||
365 | ctrl = inl(instance->ctrl_reg); | ||
366 | ctrl |= ME4600_AI_CTRL_BIT_EX_IRQ_RESET; | ||
367 | outl(ctrl, instance->ctrl_reg); | ||
368 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
369 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
370 | ctrl &= ~ME4600_AI_CTRL_BIT_EX_IRQ_RESET; | ||
371 | outl(ctrl, instance->ctrl_reg); | ||
372 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
373 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
374 | spin_unlock(instance->ctrl_reg_lock); | ||
375 | |||
376 | spin_unlock(&instance->subdevice_lock); | ||
377 | wake_up_interruptible_all(&instance->wait_queue); | ||
378 | |||
379 | return IRQ_HANDLED; | ||
380 | } | ||
381 | |||
382 | me4600_ext_irq_subdevice_t *me4600_ext_irq_constructor(uint32_t reg_base, | ||
383 | int irq, | ||
384 | spinlock_t * | ||
385 | ctrl_reg_lock) | ||
386 | { | ||
387 | me4600_ext_irq_subdevice_t *subdevice; | ||
388 | int err; | ||
389 | |||
390 | PDEBUG("executed.\n"); | ||
391 | |||
392 | /* Allocate memory for subdevice instance */ | ||
393 | subdevice = kmalloc(sizeof(me4600_ext_irq_subdevice_t), GFP_KERNEL); | ||
394 | |||
395 | if (!subdevice) { | ||
396 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
397 | return NULL; | ||
398 | } | ||
399 | |||
400 | memset(subdevice, 0, sizeof(me4600_ext_irq_subdevice_t)); | ||
401 | |||
402 | /* Initialize subdevice base class */ | ||
403 | err = me_subdevice_init(&subdevice->base); | ||
404 | |||
405 | if (err) { | ||
406 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
407 | kfree(subdevice); | ||
408 | return NULL; | ||
409 | } | ||
410 | // Initialize spin locks. | ||
411 | spin_lock_init(&subdevice->subdevice_lock); | ||
412 | |||
413 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
414 | |||
415 | /* Initialize wait queue */ | ||
416 | init_waitqueue_head(&subdevice->wait_queue); | ||
417 | |||
418 | /* Register interrupt */ | ||
419 | subdevice->irq = irq; | ||
420 | |||
421 | if (request_irq(subdevice->irq, me4600_ext_irq_isr, | ||
422 | IRQF_DISABLED | IRQF_SHARED, | ||
423 | ME4600_NAME, subdevice)) { | ||
424 | PERROR("Cannot register interrupt.\n"); | ||
425 | kfree(subdevice); | ||
426 | return NULL; | ||
427 | } | ||
428 | PINFO("Registered irq=%d.\n", subdevice->irq); | ||
429 | |||
430 | /* Initialize registers */ | ||
431 | subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; | ||
432 | subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG; | ||
433 | subdevice->ext_irq_config_reg = reg_base + ME4600_EXT_IRQ_CONFIG_REG; | ||
434 | subdevice->ext_irq_value_reg = reg_base + ME4600_EXT_IRQ_VALUE_REG; | ||
435 | #ifdef MEDEBUG_DEBUG_REG | ||
436 | subdevice->reg_base = reg_base; | ||
437 | #endif | ||
438 | |||
439 | /* Override base class methods. */ | ||
440 | subdevice->base.me_subdevice_destructor = me4600_ext_irq_destructor; | ||
441 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
442 | me4600_ext_irq_io_reset_subdevice; | ||
443 | subdevice->base.me_subdevice_io_irq_start = me4600_ext_irq_io_irq_start; | ||
444 | subdevice->base.me_subdevice_io_irq_wait = me4600_ext_irq_io_irq_wait; | ||
445 | subdevice->base.me_subdevice_io_irq_stop = me4600_ext_irq_io_irq_stop; | ||
446 | subdevice->base.me_subdevice_query_number_channels = | ||
447 | me4600_ext_irq_query_number_channels; | ||
448 | subdevice->base.me_subdevice_query_subdevice_type = | ||
449 | me4600_ext_irq_query_subdevice_type; | ||
450 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
451 | me4600_ext_irq_query_subdevice_caps; | ||
452 | |||
453 | subdevice->rised = 0; | ||
454 | subdevice->count = 0; | ||
455 | |||
456 | return subdevice; | ||
457 | } | ||
diff --git a/drivers/staging/meilhaus/me4600_ext_irq.h b/drivers/staging/meilhaus/me4600_ext_irq.h deleted file mode 100644 index 3c7b27f9e5dc..000000000000 --- a/drivers/staging/meilhaus/me4600_ext_irq.h +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ext_irq.h | ||
3 | * | ||
4 | * @brief Meilhaus ME-4000 external interrupt subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_EXT_IRQ_H_ | ||
28 | #define _ME4600_EXT_IRQ_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The subdevice class. | ||
36 | */ | ||
37 | typedef struct me4600_ext_irq_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | |||
45 | wait_queue_head_t wait_queue; | ||
46 | |||
47 | int irq; | ||
48 | |||
49 | int rised; | ||
50 | int value; | ||
51 | int count; | ||
52 | |||
53 | unsigned long ctrl_reg; | ||
54 | unsigned long irq_status_reg; | ||
55 | unsigned long ext_irq_config_reg; | ||
56 | unsigned long ext_irq_value_reg; | ||
57 | #ifdef MEDEBUG_DEBUG_REG | ||
58 | unsigned long reg_base; | ||
59 | #endif | ||
60 | } me4600_ext_irq_subdevice_t; | ||
61 | |||
62 | /** | ||
63 | * @brief The constructor to generate a external interrupt subdevice instance. | ||
64 | * | ||
65 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
66 | * @param irq The interrupt number assigned by the PCI BIOS. | ||
67 | * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. | ||
68 | * | ||
69 | * @return Pointer to new instance on success.\n | ||
70 | * NULL on error. | ||
71 | */ | ||
72 | me4600_ext_irq_subdevice_t *me4600_ext_irq_constructor(uint32_t reg_base, | ||
73 | int irq, | ||
74 | spinlock_t * | ||
75 | ctrl_reg_lock); | ||
76 | |||
77 | #endif | ||
78 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_ext_irq_reg.h b/drivers/staging/meilhaus/me4600_ext_irq_reg.h deleted file mode 100644 index 898e1e74d9e7..000000000000 --- a/drivers/staging/meilhaus/me4600_ext_irq_reg.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_ext_irq_reg.h | ||
3 | * | ||
4 | * @brief ME-4000 external interrupt subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_EXT_IRQ_REG_H_ | ||
28 | #define _ME4600_EXT_IRQ_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME4600_EXT_IRQ_CONFIG_REG 0xCC // R/_ | ||
33 | #define ME4600_EXT_IRQ_VALUE_REG 0xD0 // R/_ | ||
34 | |||
35 | #define ME4600_EXT_IRQ_CONFIG_MASK_RISING 0x0 | ||
36 | #define ME4600_EXT_IRQ_CONFIG_MASK_FALLING 0x1 | ||
37 | #define ME4600_EXT_IRQ_CONFIG_MASK_ANY 0x3 | ||
38 | #define ME4600_EXT_IRQ_CONFIG_MASK 0x3 | ||
39 | |||
40 | #endif | ||
41 | #endif | ||
diff --git a/drivers/staging/meilhaus/me4600_reg.h b/drivers/staging/meilhaus/me4600_reg.h deleted file mode 100644 index ae152bbc6a3d..000000000000 --- a/drivers/staging/meilhaus/me4600_reg.h +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /** | ||
2 | * @file me4600_reg.h | ||
3 | * | ||
4 | * @brief ME-4000 register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME4600_REG_H_ | ||
28 | #define _ME4600_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME4600_IRQ_STATUS_REG 0x9C // R/_ | ||
33 | |||
34 | #define ME4600_IRQ_STATUS_BIT_EX 0x01 | ||
35 | #define ME4600_IRQ_STATUS_BIT_LE 0x02 | ||
36 | #define ME4600_IRQ_STATUS_BIT_AI_HF 0x04 | ||
37 | #define ME4600_IRQ_STATUS_BIT_AO_0_HF 0x08 | ||
38 | #define ME4600_IRQ_STATUS_BIT_AO_1_HF 0x10 | ||
39 | #define ME4600_IRQ_STATUS_BIT_AO_2_HF 0x20 | ||
40 | #define ME4600_IRQ_STATUS_BIT_AO_3_HF 0x40 | ||
41 | #define ME4600_IRQ_STATUS_BIT_SC 0x80 | ||
42 | |||
43 | #define ME4600_IRQ_STATUS_BIT_AO_HF ME4600_IRQ_STATUS_BIT_AO_0_HF | ||
44 | |||
45 | #endif | ||
46 | #endif | ||
diff --git a/drivers/staging/meilhaus/me6000_ao.c b/drivers/staging/meilhaus/me6000_ao.c deleted file mode 100644 index 66652dc5b967..000000000000 --- a/drivers/staging/meilhaus/me6000_ao.c +++ /dev/null | |||
@@ -1,3709 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_ao.c | ||
3 | * | ||
4 | * @brief ME-6000 analog output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* Includes | ||
33 | */ | ||
34 | #include <linux/version.h> | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/uaccess.h> | ||
41 | #include <linux/types.h> | ||
42 | #include <linux/interrupt.h> | ||
43 | #include <linux/delay.h> | ||
44 | |||
45 | #include <linux/workqueue.h> | ||
46 | |||
47 | #include "medefines.h" | ||
48 | #include "meinternal.h" | ||
49 | #include "meerror.h" | ||
50 | |||
51 | #include "medebug.h" | ||
52 | #include "meids.h" | ||
53 | #include "me6000_reg.h" | ||
54 | #include "me6000_ao_reg.h" | ||
55 | #include "me6000_ao.h" | ||
56 | |||
57 | /* Defines | ||
58 | */ | ||
59 | |||
60 | static int me6000_ao_query_range_by_min_max(me_subdevice_t *subdevice, | ||
61 | int unit, | ||
62 | int *min, | ||
63 | int *max, int *maxdata, int *range); | ||
64 | |||
65 | static int me6000_ao_query_number_ranges(me_subdevice_t *subdevice, | ||
66 | int unit, int *count); | ||
67 | |||
68 | static int me6000_ao_query_range_info(me_subdevice_t *subdevice, | ||
69 | int range, | ||
70 | int *unit, | ||
71 | int *min, int *max, int *maxdata); | ||
72 | |||
73 | static int me6000_ao_query_timer(me_subdevice_t *subdevice, | ||
74 | int timer, | ||
75 | int *base_frequency, | ||
76 | long long *min_ticks, long long *max_ticks); | ||
77 | |||
78 | static int me6000_ao_query_number_channels(me_subdevice_t *subdevice, | ||
79 | int *number); | ||
80 | |||
81 | static int me6000_ao_query_subdevice_type(me_subdevice_t *subdevice, | ||
82 | int *type, int *subtype); | ||
83 | |||
84 | static int me6000_ao_query_subdevice_caps(me_subdevice_t *subdevice, | ||
85 | int *caps); | ||
86 | |||
87 | static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, | ||
88 | int cap, int *args, int count); | ||
89 | |||
90 | /** Remove subdevice. */ | ||
91 | static void me6000_ao_destructor(struct me_subdevice *subdevice); | ||
92 | |||
93 | /** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'. */ | ||
94 | static int me6000_ao_io_reset_subdevice(me_subdevice_t *subdevice, | ||
95 | struct file *filep, int flags); | ||
96 | |||
97 | /** Set output as single */ | ||
98 | static int me6000_ao_io_single_config(me_subdevice_t *subdevice, | ||
99 | struct file *filep, | ||
100 | int channel, | ||
101 | int single_config, | ||
102 | int ref, | ||
103 | int trig_chan, | ||
104 | int trig_type, int trig_edge, int flags); | ||
105 | |||
106 | /** Pass to user actual value of output. */ | ||
107 | static int me6000_ao_io_single_read(me_subdevice_t *subdevice, | ||
108 | struct file *filep, | ||
109 | int channel, | ||
110 | int *value, int time_out, int flags); | ||
111 | |||
112 | /** Write to output requed value. */ | ||
113 | static int me6000_ao_io_single_write(me_subdevice_t *subdevice, | ||
114 | struct file *filep, | ||
115 | int channel, | ||
116 | int value, int time_out, int flags); | ||
117 | |||
118 | /** Set output as streamed device. */ | ||
119 | static int me6000_ao_io_stream_config(me_subdevice_t *subdevice, | ||
120 | struct file *filep, | ||
121 | meIOStreamConfig_t *config_list, | ||
122 | int count, | ||
123 | meIOStreamTrigger_t *trigger, | ||
124 | int fifo_irq_threshold, int flags); | ||
125 | |||
126 | /** Wait for / Check empty space in buffer. */ | ||
127 | static int me6000_ao_io_stream_new_values(me_subdevice_t *subdevice, | ||
128 | struct file *filep, | ||
129 | int time_out, int *count, int flags); | ||
130 | |||
131 | /** Start streaming. */ | ||
132 | static int me6000_ao_io_stream_start(me_subdevice_t *subdevice, | ||
133 | struct file *filep, | ||
134 | int start_mode, int time_out, int flags); | ||
135 | |||
136 | /** Check actual state. / Wait for end. */ | ||
137 | static int me6000_ao_io_stream_status(me_subdevice_t *subdevice, | ||
138 | struct file *filep, | ||
139 | int wait, | ||
140 | int *status, int *values, int flags); | ||
141 | |||
142 | /** Stop streaming. */ | ||
143 | static int me6000_ao_io_stream_stop(me_subdevice_t *subdevice, | ||
144 | struct file *filep, | ||
145 | int stop_mode, int flags); | ||
146 | |||
147 | /** Write datas to buffor. */ | ||
148 | static int me6000_ao_io_stream_write(me_subdevice_t *subdevice, | ||
149 | struct file *filep, | ||
150 | int write_mode, | ||
151 | int *values, int *count, int flags); | ||
152 | |||
153 | /** Interrupt handler. Copy from buffer to FIFO. */ | ||
154 | static irqreturn_t me6000_ao_isr(int irq, void *dev_id); | ||
155 | |||
156 | /** Copy data from circular buffer to fifo (fast) in wraparound mode. */ | ||
157 | inline int ao_write_data_wraparound(me6000_ao_subdevice_t *instance, int count, | ||
158 | int start_pos); | ||
159 | |||
160 | /** Copy data from circular buffer to fifo (fast).*/ | ||
161 | inline int ao_write_data(me6000_ao_subdevice_t *instance, int count, | ||
162 | int start_pos); | ||
163 | |||
164 | /** Copy data from circular buffer to fifo (slow).*/ | ||
165 | inline int ao_write_data_pooling(me6000_ao_subdevice_t *instance, int count, | ||
166 | int start_pos); | ||
167 | |||
168 | /** Copy data from user space to circular buffer. */ | ||
169 | inline int ao_get_data_from_user(me6000_ao_subdevice_t *instance, int count, | ||
170 | int *user_values); | ||
171 | |||
172 | /** Stop presentation. Preserve FIFOs. */ | ||
173 | inline int ao_stop_immediately(me6000_ao_subdevice_t *instance); | ||
174 | |||
175 | /** Function for checking timeout in non-blocking mode. */ | ||
176 | static void me6000_ao_work_control_task(struct work_struct *work); | ||
177 | |||
178 | /* Functions | ||
179 | */ | ||
180 | |||
181 | static int me6000_ao_io_reset_subdevice(me_subdevice_t *subdevice, | ||
182 | struct file *filep, int flags) | ||
183 | { | ||
184 | me6000_ao_subdevice_t *instance; | ||
185 | int err = ME_ERRNO_SUCCESS; | ||
186 | uint32_t tmp; | ||
187 | uint32_t ctrl; | ||
188 | |||
189 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
190 | |||
191 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
192 | |||
193 | if (flags) { | ||
194 | PERROR("Invalid flag specified.\n"); | ||
195 | return ME_ERRNO_INVALID_FLAGS; | ||
196 | } | ||
197 | |||
198 | ME_SUBDEVICE_ENTER; | ||
199 | |||
200 | instance->status = ao_status_none; | ||
201 | instance->ao_control_task_flag = 0; | ||
202 | cancel_delayed_work(&instance->ao_control_task); | ||
203 | instance->timeout.delay = 0; | ||
204 | instance->timeout.start_time = jiffies; | ||
205 | |||
206 | //Stop state machine. | ||
207 | err = ao_stop_immediately(instance); | ||
208 | |||
209 | //Remove from synchronous start. | ||
210 | spin_lock(instance->preload_reg_lock); | ||
211 | tmp = inl(instance->preload_reg); | ||
212 | tmp &= | ||
213 | ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance-> | ||
214 | ao_idx); | ||
215 | outl(tmp, instance->preload_reg); | ||
216 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
217 | instance->preload_reg - instance->reg_base, tmp); | ||
218 | *instance->preload_flags &= | ||
219 | ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance-> | ||
220 | ao_idx); | ||
221 | |||
222 | //Reset triggering flag | ||
223 | *instance->triggering_flags &= ~(0x1 << instance->ao_idx); | ||
224 | spin_unlock(instance->preload_reg_lock); | ||
225 | |||
226 | if (instance->fifo) { | ||
227 | //Set single mode, dissable FIFO, dissable external trigger, block interrupt. | ||
228 | ctrl = ME6000_AO_MODE_SINGLE; | ||
229 | |||
230 | //Block ISM. | ||
231 | ctrl |= | ||
232 | (ME6000_AO_CTRL_BIT_STOP | | ||
233 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
234 | |||
235 | outl(ctrl, instance->ctrl_reg); | ||
236 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
237 | instance->reg_base, | ||
238 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
239 | //Set speed | ||
240 | outl(ME6000_AO_MIN_CHAN_TICKS - 1, instance->timer_reg); | ||
241 | //Reset interrupt latch | ||
242 | inl(instance->irq_reset_reg); | ||
243 | } | ||
244 | |||
245 | instance->hardware_stop_delay = HZ / 10; //100ms | ||
246 | |||
247 | //Set output to 0V | ||
248 | outl(0x8000, instance->single_reg); | ||
249 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
250 | instance->single_reg - instance->reg_base, 0x8000); | ||
251 | |||
252 | instance->circ_buf.head = 0; | ||
253 | instance->circ_buf.tail = 0; | ||
254 | instance->preloaded_count = 0; | ||
255 | instance->data_count = 0; | ||
256 | instance->single_value = 0x8000; | ||
257 | instance->single_value_in_fifo = 0x8000; | ||
258 | |||
259 | //Set status to signal that device is unconfigured. | ||
260 | instance->status = ao_status_none; | ||
261 | //Signal reset if user is on wait. | ||
262 | wake_up_interruptible_all(&instance->wait_queue); | ||
263 | |||
264 | ME_SUBDEVICE_EXIT; | ||
265 | |||
266 | return err; | ||
267 | } | ||
268 | |||
269 | static int me6000_ao_io_single_config(me_subdevice_t *subdevice, | ||
270 | struct file *filep, | ||
271 | int channel, | ||
272 | int single_config, | ||
273 | int ref, | ||
274 | int trig_chan, | ||
275 | int trig_type, int trig_edge, int flags) | ||
276 | { | ||
277 | me6000_ao_subdevice_t *instance; | ||
278 | int err = ME_ERRNO_SUCCESS; | ||
279 | uint32_t ctrl; | ||
280 | uint32_t sync; | ||
281 | unsigned long cpu_flags; | ||
282 | |||
283 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
284 | |||
285 | PDEBUG("executed. ID=%d\n", instance->ao_idx); | ||
286 | |||
287 | // Checking parameters | ||
288 | if (flags) { | ||
289 | PERROR | ||
290 | ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n"); | ||
291 | return ME_ERRNO_INVALID_FLAGS; | ||
292 | } | ||
293 | |||
294 | if (instance->fifo) { //Stream hardware (with or without fifo) | ||
295 | if ((trig_edge == ME_TRIG_TYPE_SW) | ||
296 | && (trig_edge != ME_TRIG_EDGE_NONE)) { | ||
297 | PERROR | ||
298 | ("Invalid trigger edge. Software trigger has not edge.\n"); | ||
299 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
300 | } | ||
301 | |||
302 | if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) { | ||
303 | switch (trig_edge) { | ||
304 | case ME_TRIG_EDGE_ANY: | ||
305 | case ME_TRIG_EDGE_RISING: | ||
306 | case ME_TRIG_EDGE_FALLING: | ||
307 | break; | ||
308 | |||
309 | default: | ||
310 | PERROR("Invalid trigger edge.\n"); | ||
311 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | if ((trig_type != ME_TRIG_TYPE_SW) | ||
316 | && (trig_type != ME_TRIG_TYPE_EXT_DIGITAL)) { | ||
317 | PERROR | ||
318 | ("Invalid trigger type. Trigger must be software or digital.\n"); | ||
319 | return ME_ERRNO_INVALID_TRIG_TYPE; | ||
320 | } | ||
321 | } else { //Single | ||
322 | if (trig_edge != ME_TRIG_EDGE_NONE) { | ||
323 | PERROR | ||
324 | ("Invalid trigger edge. Single output trigger hasn't own edge.\n"); | ||
325 | return ME_ERRNO_INVALID_TRIG_EDGE; | ||
326 | } | ||
327 | |||
328 | if (trig_type != ME_TRIG_TYPE_SW) { | ||
329 | PERROR | ||
330 | ("Invalid trigger type. Trigger must be software.\n"); | ||
331 | return ME_ERRNO_INVALID_TRIG_TYPE; | ||
332 | } | ||
333 | |||
334 | } | ||
335 | |||
336 | if ((trig_chan != ME_TRIG_CHAN_DEFAULT) | ||
337 | && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) { | ||
338 | PERROR("Invalid trigger channel specified.\n"); | ||
339 | return ME_ERRNO_INVALID_TRIG_CHAN; | ||
340 | } | ||
341 | /* | ||
342 | if ((trig_type == ME_TRIG_TYPE_EXT_DIGITAL) && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) | ||
343 | { | ||
344 | PERROR("Invalid trigger channel specified. Must be synchronous when digital is choose.\n"); | ||
345 | return ME_ERRNO_INVALID_TRIG_CHAN; | ||
346 | } | ||
347 | */ | ||
348 | if (ref != ME_REF_AO_GROUND) { | ||
349 | PERROR | ||
350 | ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n"); | ||
351 | return ME_ERRNO_INVALID_REF; | ||
352 | } | ||
353 | |||
354 | if (single_config != 0) { | ||
355 | PERROR | ||
356 | ("Invalid single config specified. Only one range for anlog outputs is available.\n"); | ||
357 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
358 | } | ||
359 | |||
360 | if (channel != 0) { | ||
361 | PERROR | ||
362 | ("Invalid channel number specified. Analog output have only one channel.\n"); | ||
363 | return ME_ERRNO_INVALID_CHANNEL; | ||
364 | } | ||
365 | |||
366 | ME_SUBDEVICE_ENTER; | ||
367 | |||
368 | //Subdevice running in stream mode! | ||
369 | if ((instance->status >= ao_status_stream_run_wait) | ||
370 | && (instance->status < ao_status_stream_end)) { | ||
371 | PERROR("Subdevice is busy.\n"); | ||
372 | ME_SUBDEVICE_EXIT; | ||
373 | |||
374 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
375 | } | ||
376 | /// @note For single all calls (config and write) are erasing previous state! | ||
377 | |||
378 | instance->status = ao_status_none; | ||
379 | |||
380 | // Correct single mirrors | ||
381 | instance->single_value_in_fifo = instance->single_value; | ||
382 | |||
383 | //Stop device | ||
384 | err = ao_stop_immediately(instance); | ||
385 | if (err) { | ||
386 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
387 | ME_SUBDEVICE_EXIT; | ||
388 | |||
389 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
390 | } | ||
391 | |||
392 | if (instance->fifo) { // Set control register. | ||
393 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
394 | // Set stop bit. Stop streaming mode (If running.). | ||
395 | ctrl = inl(instance->ctrl_reg); | ||
396 | //Reset all bits. | ||
397 | ctrl = | ||
398 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP; | ||
399 | if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) { | ||
400 | PINFO("External digital trigger.\n"); | ||
401 | |||
402 | if (trig_edge == ME_TRIG_EDGE_ANY) { | ||
403 | // ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
404 | instance->ctrl_trg = | ||
405 | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
406 | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
407 | } else if (trig_edge == ME_TRIG_EDGE_FALLING) { | ||
408 | // ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
409 | instance->ctrl_trg = | ||
410 | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
411 | } else if (trig_edge == ME_TRIG_EDGE_RISING) { | ||
412 | instance->ctrl_trg = 0x0; | ||
413 | } | ||
414 | } else if (trig_type == ME_TRIG_TYPE_SW) { | ||
415 | PDEBUG("SOFTWARE TRIGGER\n"); | ||
416 | instance->ctrl_trg = 0x0; | ||
417 | } | ||
418 | outl(ctrl, instance->ctrl_reg); | ||
419 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
420 | instance->reg_base, | ||
421 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
422 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
423 | } else { | ||
424 | PDEBUG("SOFTWARE TRIGGER\n"); | ||
425 | } | ||
426 | |||
427 | // Set preload/synchronization register. | ||
428 | spin_lock(instance->preload_reg_lock); | ||
429 | |||
430 | if (trig_type == ME_TRIG_TYPE_SW) { | ||
431 | *instance->preload_flags &= | ||
432 | ~(ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx); | ||
433 | } else //if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) | ||
434 | { | ||
435 | *instance->preload_flags |= | ||
436 | ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx; | ||
437 | } | ||
438 | |||
439 | if (trig_chan == ME_TRIG_CHAN_DEFAULT) { | ||
440 | *instance->preload_flags &= | ||
441 | ~(ME6000_AO_SYNC_HOLD << instance->ao_idx); | ||
442 | } else //if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS) | ||
443 | { | ||
444 | *instance->preload_flags |= | ||
445 | ME6000_AO_SYNC_HOLD << instance->ao_idx; | ||
446 | } | ||
447 | |||
448 | //Reset hardware register | ||
449 | sync = inl(instance->preload_reg); | ||
450 | PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
451 | instance->preload_reg - instance->reg_base, sync); | ||
452 | sync &= ~(ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx); | ||
453 | sync |= ME6000_AO_SYNC_HOLD << instance->ao_idx; | ||
454 | |||
455 | //Output configured in default mode (safe one) | ||
456 | outl(sync, instance->preload_reg); | ||
457 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
458 | instance->preload_reg - instance->reg_base, sync); | ||
459 | spin_unlock(instance->preload_reg_lock); | ||
460 | |||
461 | instance->status = ao_status_single_configured; | ||
462 | |||
463 | ME_SUBDEVICE_EXIT; | ||
464 | |||
465 | return err; | ||
466 | } | ||
467 | |||
468 | static int me6000_ao_io_single_read(me_subdevice_t *subdevice, | ||
469 | struct file *filep, | ||
470 | int channel, | ||
471 | int *value, int time_out, int flags) | ||
472 | { | ||
473 | me6000_ao_subdevice_t *instance; | ||
474 | int err = ME_ERRNO_SUCCESS; | ||
475 | |||
476 | unsigned long j; | ||
477 | unsigned long delay = 0; | ||
478 | |||
479 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
480 | |||
481 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
482 | |||
483 | if (flags & ~ME_IO_SINGLE_NONBLOCKING) { | ||
484 | PERROR("Invalid flag specified. %d\n", flags); | ||
485 | return ME_ERRNO_INVALID_FLAGS; | ||
486 | } | ||
487 | |||
488 | if ((instance->status >= ao_status_stream_configured) | ||
489 | && (instance->status <= ao_status_stream_end)) { | ||
490 | PERROR("Subdevice not configured to work in single mode!\n"); | ||
491 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
492 | } | ||
493 | |||
494 | if (channel != 0) { | ||
495 | PERROR("Invalid channel number specified.\n"); | ||
496 | return ME_ERRNO_INVALID_CHANNEL; | ||
497 | } | ||
498 | |||
499 | if (time_out < 0) { | ||
500 | PERROR("Invalid timeout specified.\n"); | ||
501 | return ME_ERRNO_INVALID_TIMEOUT; | ||
502 | } | ||
503 | |||
504 | ME_SUBDEVICE_ENTER; | ||
505 | if ((!flags) && (instance->status == ao_status_single_run_wait)) { //Blocking mode. Wait for trigger. | ||
506 | if (time_out) { | ||
507 | delay = (time_out * HZ) / 1000; | ||
508 | if (delay == 0) | ||
509 | delay = 1; | ||
510 | } | ||
511 | |||
512 | j = jiffies; | ||
513 | |||
514 | //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. | ||
515 | wait_event_interruptible_timeout(instance->wait_queue, | ||
516 | (instance->status != | ||
517 | ao_status_single_run_wait), | ||
518 | (delay) ? delay : LONG_MAX); | ||
519 | |||
520 | if (instance->status == ao_status_none) { | ||
521 | PDEBUG("Single canceled.\n"); | ||
522 | err = ME_ERRNO_CANCELLED; | ||
523 | } | ||
524 | |||
525 | if (signal_pending(current)) { | ||
526 | PERROR("Wait on start of state machine interrupted.\n"); | ||
527 | instance->status = ao_status_none; | ||
528 | ao_stop_immediately(instance); | ||
529 | err = ME_ERRNO_SIGNAL; | ||
530 | } | ||
531 | |||
532 | if ((delay) && ((jiffies - j) >= delay)) { | ||
533 | PDEBUG("Timeout reached.\n"); | ||
534 | err = ME_ERRNO_TIMEOUT; | ||
535 | } | ||
536 | |||
537 | *value = | ||
538 | (!err) ? instance->single_value_in_fifo : instance-> | ||
539 | single_value; | ||
540 | } else { //Non-blocking mode | ||
541 | //Read value | ||
542 | *value = instance->single_value; | ||
543 | } | ||
544 | |||
545 | ME_SUBDEVICE_EXIT; | ||
546 | |||
547 | return err; | ||
548 | } | ||
549 | |||
550 | static int me6000_ao_io_single_write(me_subdevice_t *subdevice, | ||
551 | struct file *filep, | ||
552 | int channel, | ||
553 | int value, int time_out, int flags) | ||
554 | { | ||
555 | me6000_ao_subdevice_t *instance; | ||
556 | int err = ME_ERRNO_SUCCESS; | ||
557 | unsigned long cpu_flags; | ||
558 | unsigned long j; | ||
559 | unsigned long delay = 0; | ||
560 | |||
561 | uint32_t sync_mask; | ||
562 | uint32_t mode; | ||
563 | |||
564 | uint32_t tmp; | ||
565 | |||
566 | /// Workaround for mix-mode - begin | ||
567 | uint32_t ctrl = 0x0; | ||
568 | uint32_t status; | ||
569 | /// Workaround for mix-mode - end | ||
570 | |||
571 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
572 | |||
573 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
574 | |||
575 | if (flags & | ||
576 | ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS | | ||
577 | ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { | ||
578 | PERROR("Invalid flag specified.\n"); | ||
579 | return ME_ERRNO_INVALID_FLAGS; | ||
580 | } | ||
581 | |||
582 | if ((instance->status == ao_status_none) | ||
583 | || (instance->status > ao_status_single_end)) { | ||
584 | PERROR("Subdevice not configured to work in single mode!\n"); | ||
585 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
586 | } | ||
587 | |||
588 | if (channel != 0) { | ||
589 | PERROR("Invalid channel number specified.\n"); | ||
590 | return ME_ERRNO_INVALID_CHANNEL; | ||
591 | } | ||
592 | |||
593 | if (value & ~ME6000_AO_MAX_DATA) { | ||
594 | PERROR("Invalid value provided.\n"); | ||
595 | return ME_ERRNO_VALUE_OUT_OF_RANGE; | ||
596 | } | ||
597 | |||
598 | if (time_out < 0) { | ||
599 | PERROR("Invalid timeout specified.\n"); | ||
600 | return ME_ERRNO_INVALID_TIMEOUT; | ||
601 | } | ||
602 | |||
603 | ME_SUBDEVICE_ENTER; | ||
604 | |||
605 | /// @note For single all calls (config and write) are erasing previous state! | ||
606 | |||
607 | //Cancel control task | ||
608 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
609 | instance->ao_control_task_flag = 0; | ||
610 | cancel_delayed_work(&instance->ao_control_task); | ||
611 | |||
612 | // Correct single mirrors | ||
613 | instance->single_value_in_fifo = instance->single_value; | ||
614 | |||
615 | //Stop device | ||
616 | err = ao_stop_immediately(instance); | ||
617 | if (err) { | ||
618 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
619 | ME_SUBDEVICE_EXIT; | ||
620 | |||
621 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
622 | } | ||
623 | |||
624 | if (time_out) { | ||
625 | delay = (time_out * HZ) / 1000; | ||
626 | |||
627 | if (delay == 0) | ||
628 | delay = 1; | ||
629 | } | ||
630 | |||
631 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
632 | |||
633 | instance->single_value_in_fifo = value; | ||
634 | |||
635 | if (instance->fifo) { | ||
636 | ctrl = inl(instance->ctrl_reg); | ||
637 | } | ||
638 | |||
639 | if (instance->fifo & ME6000_AO_HAS_FIFO) { /// Workaround for mix-mode - begin | ||
640 | //Set speed | ||
641 | outl(ME6000_AO_MIN_CHAN_TICKS - 1, instance->timer_reg); | ||
642 | PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
643 | instance->reg_base, | ||
644 | instance->timer_reg - instance->reg_base, | ||
645 | (int)ME6000_AO_MIN_CHAN_TICKS); | ||
646 | instance->hardware_stop_delay = HZ / 10; //100ms | ||
647 | |||
648 | status = inl(instance->status_reg); | ||
649 | |||
650 | //Set the continous mode. | ||
651 | ctrl &= ~ME6000_AO_CTRL_MODE_MASK; | ||
652 | ctrl |= ME6000_AO_MODE_CONTINUOUS; | ||
653 | |||
654 | //Prepare FIFO | ||
655 | if (!(ctrl & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. | ||
656 | PINFO("Enableing FIFO.\n"); | ||
657 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
658 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; | ||
659 | } else { //Check if FIFO is empty | ||
660 | if (status & ME6000_AO_STATUS_BIT_EF) { //FIFO not empty | ||
661 | PINFO("Reseting FIFO.\n"); | ||
662 | ctrl &= | ||
663 | ~(ME6000_AO_CTRL_BIT_ENABLE_FIFO | | ||
664 | ME6000_AO_CTRL_BIT_ENABLE_IRQ); | ||
665 | outl(ctrl, instance->ctrl_reg); | ||
666 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
667 | instance->reg_base, | ||
668 | instance->ctrl_reg - | ||
669 | instance->reg_base, ctrl); | ||
670 | |||
671 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; | ||
672 | } else { //FIFO empty, only interrupt needs to be disabled! | ||
673 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
674 | } | ||
675 | } | ||
676 | |||
677 | outl(ctrl, instance->ctrl_reg); | ||
678 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
679 | instance->reg_base, | ||
680 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
681 | |||
682 | //Reset interrupt latch | ||
683 | inl(instance->irq_reset_reg); | ||
684 | |||
685 | //Write output - 1 value to FIFO | ||
686 | if (instance->ao_idx & 0x1) { | ||
687 | outl(value <<= 16, instance->fifo_reg); | ||
688 | PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
689 | instance->reg_base, | ||
690 | instance->fifo_reg - instance->reg_base, | ||
691 | value <<= 16); | ||
692 | } else { | ||
693 | outl(value, instance->fifo_reg); | ||
694 | PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
695 | instance->reg_base, | ||
696 | instance->fifo_reg - instance->reg_base, | ||
697 | value); | ||
698 | } | ||
699 | /// Workaround for mix-mode - end | ||
700 | } else { //No FIFO - always in single mode | ||
701 | //Write value | ||
702 | PDEBUG("Write value\n"); | ||
703 | outl(value, instance->single_reg); | ||
704 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
705 | instance->reg_base, | ||
706 | instance->single_reg - instance->reg_base, value); | ||
707 | } | ||
708 | |||
709 | mode = *instance->preload_flags >> instance->ao_idx; | ||
710 | mode &= (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG); | ||
711 | |||
712 | PINFO("Triggering mode: 0x%08x\n", mode); | ||
713 | |||
714 | spin_lock(instance->preload_reg_lock); | ||
715 | sync_mask = inl(instance->preload_reg); | ||
716 | PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
717 | instance->preload_reg - instance->reg_base, sync_mask); | ||
718 | switch (mode) { | ||
719 | case 0: //0x00000000: Individual software | ||
720 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
721 | |||
722 | if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode | ||
723 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
724 | if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. | ||
725 | sync_mask &= | ||
726 | ~((ME6000_AO_SYNC_EXT_TRIG | | ||
727 | ME6000_AO_SYNC_HOLD) << instance-> | ||
728 | ao_idx); | ||
729 | |||
730 | outl(sync_mask, instance->preload_reg); | ||
731 | PDEBUG_REG | ||
732 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
733 | instance->reg_base, | ||
734 | instance->preload_reg - instance->reg_base, | ||
735 | sync_mask); | ||
736 | } | ||
737 | } else { // No FIFO - Single mode: In this case resetting 'ME6000_AO_SYNC_HOLD' will trigger output. | ||
738 | 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. | ||
739 | sync_mask &= | ||
740 | ~(ME6000_AO_SYNC_EXT_TRIG << instance-> | ||
741 | ao_idx); | ||
742 | sync_mask |= | ||
743 | ME6000_AO_SYNC_HOLD << instance->ao_idx; | ||
744 | |||
745 | outl(sync_mask, instance->preload_reg); | ||
746 | PDEBUG_REG | ||
747 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
748 | instance->reg_base, | ||
749 | instance->preload_reg - instance->reg_base, | ||
750 | sync_mask); | ||
751 | } | ||
752 | } | ||
753 | instance->single_value = value; | ||
754 | break; | ||
755 | |||
756 | case ME6000_AO_SYNC_EXT_TRIG: //0x00010000: Individual hardware | ||
757 | PDEBUG("DIGITAL TRIGGER\n"); | ||
758 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
759 | |||
760 | if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode | ||
761 | if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. | ||
762 | sync_mask &= | ||
763 | ~((ME6000_AO_SYNC_EXT_TRIG | | ||
764 | ME6000_AO_SYNC_HOLD) << instance-> | ||
765 | ao_idx); | ||
766 | |||
767 | outl(sync_mask, instance->preload_reg); | ||
768 | PDEBUG_REG | ||
769 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
770 | instance->reg_base, | ||
771 | instance->preload_reg - instance->reg_base, | ||
772 | sync_mask); | ||
773 | } | ||
774 | } else { // No FIFO - Single mode | ||
775 | if ((sync_mask & | ||
776 | ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << | ||
777 | instance->ao_idx)) != ME6000_AO_SYNC_HOLD) { | ||
778 | //Now we can set correct mode | ||
779 | sync_mask &= | ||
780 | ~(ME6000_AO_SYNC_EXT_TRIG << instance-> | ||
781 | ao_idx); | ||
782 | sync_mask |= | ||
783 | ME6000_AO_SYNC_HOLD << instance->ao_idx; | ||
784 | |||
785 | outl(sync_mask, instance->preload_reg); | ||
786 | PDEBUG_REG | ||
787 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
788 | instance->reg_base, | ||
789 | instance->preload_reg - instance->reg_base, | ||
790 | sync_mask); | ||
791 | } | ||
792 | } | ||
793 | break; | ||
794 | |||
795 | case ME6000_AO_SYNC_HOLD: //0x00000001: Synchronous software | ||
796 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
797 | |||
798 | if ((sync_mask & | ||
799 | ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << | ||
800 | instance->ao_idx)) != | ||
801 | (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG)) { | ||
802 | //Now we can set correct mode | ||
803 | sync_mask |= | ||
804 | ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx; | ||
805 | sync_mask |= ME6000_AO_SYNC_HOLD << instance->ao_idx; | ||
806 | outl(sync_mask, instance->preload_reg); | ||
807 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
808 | instance->reg_base, | ||
809 | instance->preload_reg - instance->reg_base, | ||
810 | sync_mask); | ||
811 | } | ||
812 | //Set triggering flag | ||
813 | *instance->triggering_flags |= 0x1 << instance->ao_idx; | ||
814 | break; | ||
815 | |||
816 | case (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG): //0x00010001: Synchronous hardware | ||
817 | PDEBUG("DIGITAL TRIGGER\n"); | ||
818 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
819 | |||
820 | if ((sync_mask & | ||
821 | ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << | ||
822 | instance->ao_idx)) != | ||
823 | (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG)) { | ||
824 | //Now we can set correct mode | ||
825 | sync_mask |= | ||
826 | (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << | ||
827 | instance->ao_idx; | ||
828 | outl(sync_mask, instance->preload_reg); | ||
829 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
830 | instance->reg_base, | ||
831 | instance->preload_reg - instance->reg_base, | ||
832 | sync_mask); | ||
833 | } | ||
834 | //Set triggering flag | ||
835 | *instance->triggering_flags |= 0x1 << instance->ao_idx; | ||
836 | break; | ||
837 | } | ||
838 | // spin_unlock(instance->preload_reg_lock); // Moved down. | ||
839 | |||
840 | if (instance->fifo) { //Activate ISM (remove 'stop' bits) | ||
841 | ctrl &= | ||
842 | ~(ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
843 | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); | ||
844 | ctrl |= instance->ctrl_trg; | ||
845 | ctrl &= | ||
846 | ~(ME6000_AO_CTRL_BIT_STOP | | ||
847 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
848 | |||
849 | outl(ctrl, instance->ctrl_reg); | ||
850 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
851 | instance->reg_base, | ||
852 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
853 | } | ||
854 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
855 | |||
856 | /// @note When flag 'ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS' is set than output is triggered. ALWAYS! | ||
857 | |||
858 | PINFO("<%s> start mode= 0x%08x %s\n", __func__, mode, | ||
859 | (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) ? "SYNCHRONOUS" : | ||
860 | ""); | ||
861 | if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode | ||
862 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs | ||
863 | //Add channel to start list | ||
864 | outl(sync_mask | | ||
865 | (ME6000_AO_SYNC_HOLD << instance->ao_idx), | ||
866 | instance->preload_reg); | ||
867 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
868 | instance->reg_base, | ||
869 | instance->preload_reg - instance->reg_base, | ||
870 | sync_mask | (ME6000_AO_SYNC_HOLD << | ||
871 | instance->ao_idx)); | ||
872 | |||
873 | //Fire | ||
874 | PINFO | ||
875 | ("Fired all software synchronous outputs by software trigger.\n"); | ||
876 | outl(0x8000, instance->single_reg); | ||
877 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
878 | instance->reg_base, | ||
879 | instance->single_reg - instance->reg_base, | ||
880 | 0x8000); | ||
881 | |||
882 | //Restore save settings | ||
883 | outl(sync_mask, instance->preload_reg); | ||
884 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
885 | instance->reg_base, | ||
886 | instance->preload_reg - instance->reg_base, | ||
887 | sync_mask); | ||
888 | |||
889 | } else if (!mode) { //Trigger outputs | ||
890 | /* //Remove channel from start list | ||
891 | outl(sync_mask & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); | ||
892 | 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)); | ||
893 | */ | ||
894 | //Fire | ||
895 | PINFO("Software trigger.\n"); | ||
896 | outl(0x8000, instance->single_reg); | ||
897 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
898 | instance->reg_base, | ||
899 | instance->single_reg - instance->reg_base, | ||
900 | 0x8000); | ||
901 | |||
902 | /* //Restore save settings | ||
903 | outl(sync_mask, instance->preload_reg); | ||
904 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask); | ||
905 | */ | ||
906 | } | ||
907 | /// @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. | ||
908 | /// @note Because triggering is not working it can not be add to synchronous list. First 4 channels don't need this information, anyway. | ||
909 | *instance->triggering_flags &= 0xFFFFFFF0; | ||
910 | } else { // No FIFO - Single mode | ||
911 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Fired all software synchronous outputs. | ||
912 | tmp = ~(*instance->preload_flags | 0xFFFF0000); | ||
913 | PINFO | ||
914 | ("Fired all software synchronous outputs. mask:0x%08x\n", | ||
915 | tmp); | ||
916 | tmp |= sync_mask & 0xFFFF0000; | ||
917 | // Add this channel to list | ||
918 | tmp &= ~(ME6000_AO_SYNC_HOLD << instance->ao_idx); | ||
919 | |||
920 | //Fire | ||
921 | PINFO("Software trigger.\n"); | ||
922 | outl(tmp, instance->preload_reg); | ||
923 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
924 | instance->reg_base, | ||
925 | instance->preload_reg - instance->reg_base, | ||
926 | tmp); | ||
927 | |||
928 | //Restore save settings | ||
929 | outl(sync_mask, instance->preload_reg); | ||
930 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
931 | instance->reg_base, | ||
932 | instance->preload_reg - instance->reg_base, | ||
933 | sync_mask); | ||
934 | |||
935 | //Set all as triggered. | ||
936 | *instance->triggering_flags = 0x0; | ||
937 | } else if (!mode) { // Add this channel to list | ||
938 | outl(sync_mask & | ||
939 | ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), | ||
940 | instance->preload_reg); | ||
941 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
942 | instance->reg_base, | ||
943 | instance->preload_reg - instance->reg_base, | ||
944 | sync_mask & ~(ME6000_AO_SYNC_HOLD << | ||
945 | instance->ao_idx)); | ||
946 | |||
947 | //Fire | ||
948 | PINFO("Software trigger.\n"); | ||
949 | |||
950 | //Restore save settings | ||
951 | outl(sync_mask, instance->preload_reg); | ||
952 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
953 | instance->reg_base, | ||
954 | instance->preload_reg - instance->reg_base, | ||
955 | sync_mask); | ||
956 | |||
957 | //Set all as triggered. | ||
958 | *instance->triggering_flags = 0x0; | ||
959 | } | ||
960 | |||
961 | } | ||
962 | spin_unlock(instance->preload_reg_lock); | ||
963 | |||
964 | instance->status = ao_status_single_run_wait; | ||
965 | |||
966 | instance->timeout.delay = delay; | ||
967 | instance->timeout.start_time = jiffies; | ||
968 | instance->ao_control_task_flag = 1; | ||
969 | queue_delayed_work(instance->me6000_workqueue, | ||
970 | &instance->ao_control_task, 1); | ||
971 | |||
972 | if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { | ||
973 | j = jiffies; | ||
974 | |||
975 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
976 | wait_event_interruptible_timeout(instance->wait_queue, | ||
977 | (instance->status != | ||
978 | ao_status_single_run_wait), | ||
979 | (delay) ? delay + | ||
980 | 1 : LONG_MAX); | ||
981 | |||
982 | if (instance->status != ao_status_single_end) { | ||
983 | PDEBUG("Single canceled.\n"); | ||
984 | err = ME_ERRNO_CANCELLED; | ||
985 | } | ||
986 | |||
987 | if (signal_pending(current)) { | ||
988 | PERROR("Wait on start of state machine interrupted.\n"); | ||
989 | instance->ao_control_task_flag = 0; | ||
990 | cancel_delayed_work(&instance->ao_control_task); | ||
991 | ao_stop_immediately(instance); | ||
992 | instance->status = ao_status_none; | ||
993 | err = ME_ERRNO_SIGNAL; | ||
994 | } | ||
995 | |||
996 | if ((delay) && ((jiffies - j) >= delay)) { | ||
997 | if (instance->status == ao_status_single_end) { | ||
998 | PDEBUG("Timeout reached.\n"); | ||
999 | } else if ((jiffies - j) > delay) { | ||
1000 | PERROR | ||
1001 | ("Timeout reached. Not handled by control task!\n"); | ||
1002 | ao_stop_immediately(instance); | ||
1003 | } else { | ||
1004 | PERROR | ||
1005 | ("Timeout reached. Signal come but status is strange: %d\n", | ||
1006 | instance->status); | ||
1007 | ao_stop_immediately(instance); | ||
1008 | } | ||
1009 | |||
1010 | instance->ao_control_task_flag = 0; | ||
1011 | cancel_delayed_work(&instance->ao_control_task); | ||
1012 | instance->status = ao_status_single_end; | ||
1013 | err = ME_ERRNO_TIMEOUT; | ||
1014 | } | ||
1015 | } | ||
1016 | |||
1017 | ME_SUBDEVICE_EXIT; | ||
1018 | |||
1019 | return err; | ||
1020 | } | ||
1021 | |||
1022 | static int me6000_ao_io_stream_config(me_subdevice_t *subdevice, | ||
1023 | struct file *filep, | ||
1024 | meIOStreamConfig_t *config_list, | ||
1025 | int count, | ||
1026 | meIOStreamTrigger_t *trigger, | ||
1027 | int fifo_irq_threshold, int flags) | ||
1028 | { | ||
1029 | me6000_ao_subdevice_t *instance; | ||
1030 | int err = ME_ERRNO_SUCCESS; | ||
1031 | uint32_t ctrl; | ||
1032 | unsigned long cpu_flags; | ||
1033 | uint64_t conv_ticks; | ||
1034 | unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; | ||
1035 | unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; | ||
1036 | |||
1037 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
1038 | |||
1039 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1040 | |||
1041 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { | ||
1042 | PERROR("Not a streaming ao.\n"); | ||
1043 | return ME_ERRNO_NOT_SUPPORTED; | ||
1044 | } | ||
1045 | |||
1046 | conv_ticks = | ||
1047 | (uint64_t) conv_start_ticks_low + | ||
1048 | ((uint64_t) conv_start_ticks_high << 32); | ||
1049 | |||
1050 | if (flags & | ||
1051 | ~(ME_IO_STREAM_CONFIG_HARDWARE_ONLY | | ||
1052 | ME_IO_STREAM_CONFIG_WRAPAROUND)) { | ||
1053 | PERROR("Invalid flags.\n"); | ||
1054 | return ME_ERRNO_INVALID_FLAGS; | ||
1055 | } | ||
1056 | |||
1057 | if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { | ||
1058 | if (!(flags & ME_IO_STREAM_CONFIG_WRAPAROUND)) { | ||
1059 | PERROR | ||
1060 | ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n"); | ||
1061 | return ME_ERRNO_INVALID_FLAGS; | ||
1062 | } | ||
1063 | |||
1064 | if ((trigger->iAcqStopTrigType != ME_TRIG_TYPE_NONE) | ||
1065 | || (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE)) { | ||
1066 | PERROR | ||
1067 | ("Hardware wraparound mode must be in infinite mode.\n"); | ||
1068 | return ME_ERRNO_INVALID_FLAGS; | ||
1069 | } | ||
1070 | } | ||
1071 | |||
1072 | if (count != 1) { | ||
1073 | PERROR("Only 1 entry in config list acceptable.\n"); | ||
1074 | return ME_ERRNO_INVALID_CONFIG_LIST_COUNT; | ||
1075 | } | ||
1076 | |||
1077 | if (config_list[0].iChannel != 0) { | ||
1078 | PERROR("Invalid channel number specified.\n"); | ||
1079 | return ME_ERRNO_INVALID_CHANNEL; | ||
1080 | } | ||
1081 | |||
1082 | if (config_list[0].iStreamConfig != 0) { | ||
1083 | PERROR("Only one range available.\n"); | ||
1084 | return ME_ERRNO_INVALID_STREAM_CONFIG; | ||
1085 | } | ||
1086 | |||
1087 | if (config_list[0].iRef != ME_REF_AO_GROUND) { | ||
1088 | PERROR("Output is referenced to ground.\n"); | ||
1089 | return ME_ERRNO_INVALID_REF; | ||
1090 | } | ||
1091 | |||
1092 | if ((trigger->iAcqStartTicksLow != 0) | ||
1093 | || (trigger->iAcqStartTicksHigh != 0)) { | ||
1094 | PERROR | ||
1095 | ("Invalid acquisition start trigger argument specified.\n"); | ||
1096 | return ME_ERRNO_INVALID_ACQ_START_ARG; | ||
1097 | } | ||
1098 | |||
1099 | if (config_list[0].iFlags) { | ||
1100 | PERROR("Invalid config list flag.\n"); | ||
1101 | return ME_ERRNO_INVALID_FLAGS; | ||
1102 | } | ||
1103 | |||
1104 | if ((trigger->iAcqStartTrigType != ME_TRIG_TYPE_SW) | ||
1105 | && (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_DIGITAL)) { | ||
1106 | PERROR("Invalid acquisition start trigger type specified.\n"); | ||
1107 | return ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; | ||
1108 | } | ||
1109 | |||
1110 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { | ||
1111 | switch (trigger->iAcqStartTrigEdge) { | ||
1112 | case ME_TRIG_EDGE_RISING: | ||
1113 | case ME_TRIG_EDGE_FALLING: | ||
1114 | case ME_TRIG_EDGE_ANY: | ||
1115 | break; | ||
1116 | |||
1117 | default: | ||
1118 | PERROR | ||
1119 | ("Invalid acquisition start trigger edge specified.\n"); | ||
1120 | return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
1121 | } | ||
1122 | } | ||
1123 | |||
1124 | if ((trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) | ||
1125 | && (trigger->iAcqStartTrigEdge != ME_TRIG_TYPE_NONE)) { | ||
1126 | PERROR("Invalid acquisition start trigger edge specified.\n"); | ||
1127 | return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; | ||
1128 | } | ||
1129 | |||
1130 | if (trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) { | ||
1131 | PERROR("Invalid scan start trigger type specified.\n"); | ||
1132 | return ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; | ||
1133 | } | ||
1134 | |||
1135 | if (trigger->iConvStartTrigType != ME_TRIG_TYPE_TIMER) { | ||
1136 | PERROR("Invalid conv start trigger type specified.\n"); | ||
1137 | return ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; | ||
1138 | } | ||
1139 | |||
1140 | if ((conv_ticks < ME6000_AO_MIN_CHAN_TICKS) | ||
1141 | || (conv_ticks > ME6000_AO_MAX_CHAN_TICKS)) { | ||
1142 | PERROR("Invalid conv start trigger argument specified.\n"); | ||
1143 | return ME_ERRNO_INVALID_CONV_START_ARG; | ||
1144 | } | ||
1145 | |||
1146 | if (trigger->iAcqStartTicksLow || trigger->iAcqStartTicksHigh) { | ||
1147 | PERROR("Invalid acq start trigger argument specified.\n"); | ||
1148 | return ME_ERRNO_INVALID_ACQ_START_ARG; | ||
1149 | } | ||
1150 | |||
1151 | if (trigger->iScanStartTicksLow || trigger->iScanStartTicksHigh) { | ||
1152 | PERROR("Invalid scan start trigger argument specified.\n"); | ||
1153 | return ME_ERRNO_INVALID_SCAN_START_ARG; | ||
1154 | } | ||
1155 | |||
1156 | switch (trigger->iScanStopTrigType) { | ||
1157 | case ME_TRIG_TYPE_NONE: | ||
1158 | if (trigger->iScanStopCount != 0) { | ||
1159 | PERROR("Invalid scan stop count specified.\n"); | ||
1160 | return ME_ERRNO_INVALID_SCAN_STOP_ARG; | ||
1161 | } | ||
1162 | break; | ||
1163 | |||
1164 | case ME_TRIG_TYPE_COUNT: | ||
1165 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
1166 | if (trigger->iScanStopCount <= 0) { | ||
1167 | PERROR("Invalid scan stop count specified.\n"); | ||
1168 | return ME_ERRNO_INVALID_SCAN_STOP_ARG; | ||
1169 | } | ||
1170 | } else { | ||
1171 | PERROR("The continous mode has not 'scan' contects.\n"); | ||
1172 | return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1173 | } | ||
1174 | break; | ||
1175 | |||
1176 | default: | ||
1177 | PERROR("Invalid scan stop trigger type specified.\n"); | ||
1178 | return ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; | ||
1179 | } | ||
1180 | |||
1181 | switch (trigger->iAcqStopTrigType) { | ||
1182 | case ME_TRIG_TYPE_NONE: | ||
1183 | if (trigger->iAcqStopCount != 0) { | ||
1184 | PERROR("Invalid acq stop count specified.\n"); | ||
1185 | return ME_ERRNO_INVALID_ACQ_STOP_ARG; | ||
1186 | } | ||
1187 | break; | ||
1188 | |||
1189 | case ME_TRIG_TYPE_COUNT: | ||
1190 | if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { | ||
1191 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1192 | return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1193 | } | ||
1194 | |||
1195 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { | ||
1196 | if (trigger->iAcqStopCount <= 0) { | ||
1197 | PERROR | ||
1198 | ("The continous mode has not 'scan' contects.\n"); | ||
1199 | return ME_ERRNO_INVALID_ACQ_STOP_ARG; | ||
1200 | } | ||
1201 | } | ||
1202 | // else | ||
1203 | // { | ||
1204 | // PERROR("Invalid acq stop trigger type specified.\n"); | ||
1205 | // return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1206 | // } | ||
1207 | |||
1208 | break; | ||
1209 | |||
1210 | default: | ||
1211 | PERROR("Invalid acq stop trigger type specified.\n"); | ||
1212 | return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; | ||
1213 | } | ||
1214 | |||
1215 | switch (trigger->iAcqStartTrigChan) { | ||
1216 | case ME_TRIG_CHAN_DEFAULT: | ||
1217 | case ME_TRIG_CHAN_SYNCHRONOUS: | ||
1218 | break; | ||
1219 | |||
1220 | default: | ||
1221 | PERROR("Invalid acq start trigger channel specified.\n"); | ||
1222 | return ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; | ||
1223 | } | ||
1224 | |||
1225 | ME_SUBDEVICE_ENTER; | ||
1226 | |||
1227 | //Stop device | ||
1228 | |||
1229 | //Cancel control task | ||
1230 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
1231 | instance->ao_control_task_flag = 0; | ||
1232 | cancel_delayed_work(&instance->ao_control_task); | ||
1233 | |||
1234 | //Check if state machine is stopped. | ||
1235 | err = ao_stop_immediately(instance); | ||
1236 | if (err) { | ||
1237 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
1238 | ME_SUBDEVICE_EXIT; | ||
1239 | |||
1240 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
1241 | } | ||
1242 | |||
1243 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1244 | //Reset control register. Block all actions. Disable IRQ. Disable FIFO. | ||
1245 | ctrl = ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP; | ||
1246 | outl(ctrl, instance->ctrl_reg); | ||
1247 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1248 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1249 | |||
1250 | //Reset interrupt latch | ||
1251 | inl(instance->irq_reset_reg); | ||
1252 | |||
1253 | //This is paranoic, but to be sure. | ||
1254 | instance->preloaded_count = 0; | ||
1255 | instance->data_count = 0; | ||
1256 | instance->circ_buf.head = 0; | ||
1257 | instance->circ_buf.tail = 0; | ||
1258 | |||
1259 | /* Set mode. */ | ||
1260 | if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { //Wraparound | ||
1261 | if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { //Hardware wraparound | ||
1262 | PINFO("Hardware wraparound.\n"); | ||
1263 | ctrl |= ME6000_AO_MODE_WRAPAROUND; | ||
1264 | instance->mode = ME6000_AO_HW_WRAP_MODE; | ||
1265 | } else { //Software wraparound | ||
1266 | PINFO("Software wraparound.\n"); | ||
1267 | ctrl |= ME6000_AO_MODE_CONTINUOUS; | ||
1268 | instance->mode = ME6000_AO_SW_WRAP_MODE; | ||
1269 | } | ||
1270 | } else { //Continous | ||
1271 | PINFO("Continous.\n"); | ||
1272 | ctrl |= ME6000_AO_MODE_CONTINUOUS; | ||
1273 | instance->mode = ME6000_AO_CONTINOUS; | ||
1274 | } | ||
1275 | |||
1276 | //Set the trigger edge. | ||
1277 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Set the trigger type and edge for external trigger. | ||
1278 | PINFO("External digital trigger.\n"); | ||
1279 | instance->start_mode = ME6000_AO_EXT_TRIG; | ||
1280 | |||
1281 | switch (trigger->iAcqStartTrigEdge) { | ||
1282 | case ME_TRIG_EDGE_RISING: | ||
1283 | PINFO("Set the trigger edge: rising.\n"); | ||
1284 | instance->ctrl_trg = 0x0; | ||
1285 | break; | ||
1286 | |||
1287 | case ME_TRIG_EDGE_FALLING: | ||
1288 | PINFO("Set the trigger edge: falling.\n"); | ||
1289 | // ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
1290 | instance->ctrl_trg = ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; | ||
1291 | break; | ||
1292 | |||
1293 | case ME_TRIG_EDGE_ANY: | ||
1294 | PINFO("Set the trigger edge: both edges.\n"); | ||
1295 | // ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
1296 | instance->ctrl_trg = | ||
1297 | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
1298 | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; | ||
1299 | break; | ||
1300 | } | ||
1301 | } else { | ||
1302 | PINFO("Internal software trigger.\n"); | ||
1303 | instance->start_mode = 0; | ||
1304 | } | ||
1305 | |||
1306 | //Set the stop mode and value. | ||
1307 | if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of data | ||
1308 | instance->stop_mode = ME6000_AO_ACQ_STOP_MODE; | ||
1309 | instance->stop_count = trigger->iAcqStopCount; | ||
1310 | } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of 'scans' | ||
1311 | instance->stop_mode = ME6000_AO_SCAN_STOP_MODE; | ||
1312 | instance->stop_count = trigger->iScanStopCount; | ||
1313 | } else { //Infinite | ||
1314 | instance->stop_mode = ME6000_AO_INF_STOP_MODE; | ||
1315 | instance->stop_count = 0; | ||
1316 | } | ||
1317 | |||
1318 | PINFO("Stop count: %d.\n", instance->stop_count); | ||
1319 | |||
1320 | if (trigger->iAcqStartTrigChan == ME_TRIG_CHAN_SYNCHRONOUS) { //Synchronous start | ||
1321 | instance->start_mode |= ME6000_AO_SYNC_HOLD; | ||
1322 | if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Externaly triggered | ||
1323 | PINFO("Synchronous start. Externaly trigger active.\n"); | ||
1324 | instance->start_mode |= ME6000_AO_SYNC_EXT_TRIG; | ||
1325 | } | ||
1326 | #ifdef MEDEBUG_INFO | ||
1327 | else { | ||
1328 | PINFO | ||
1329 | ("Synchronous start. Externaly trigger dissabled.\n"); | ||
1330 | } | ||
1331 | #endif | ||
1332 | |||
1333 | } | ||
1334 | //Set speed | ||
1335 | outl(conv_ticks - 2, instance->timer_reg); | ||
1336 | PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%llx\n", instance->reg_base, | ||
1337 | instance->timer_reg - instance->reg_base, conv_ticks - 2); | ||
1338 | instance->hardware_stop_delay = (int)(conv_ticks * HZ) / ME6000_AO_BASE_FREQUENCY; //<== MUST be with cast! | ||
1339 | |||
1340 | // Write the control word | ||
1341 | outl(ctrl, instance->ctrl_reg); | ||
1342 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1343 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1344 | |||
1345 | //Set status. | ||
1346 | instance->status = ao_status_stream_configured; | ||
1347 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
1348 | |||
1349 | ME_SUBDEVICE_EXIT; | ||
1350 | |||
1351 | return err; | ||
1352 | } | ||
1353 | |||
1354 | static int me6000_ao_io_stream_new_values(me_subdevice_t *subdevice, | ||
1355 | struct file *filep, | ||
1356 | int time_out, int *count, int flags) | ||
1357 | { | ||
1358 | me6000_ao_subdevice_t *instance; | ||
1359 | int err = ME_ERRNO_SUCCESS; | ||
1360 | long t = 0; | ||
1361 | long j; | ||
1362 | |||
1363 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
1364 | |||
1365 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1366 | |||
1367 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { | ||
1368 | PERROR("Not a streaming ao.\n"); | ||
1369 | return ME_ERRNO_NOT_SUPPORTED; | ||
1370 | } | ||
1371 | |||
1372 | if (flags) { | ||
1373 | PERROR("Invalid flag specified.\n"); | ||
1374 | return ME_ERRNO_INVALID_FLAGS; | ||
1375 | } | ||
1376 | |||
1377 | if (!instance->circ_buf.buf) { | ||
1378 | PERROR("Circular buffer not exists.\n"); | ||
1379 | return ME_ERRNO_INTERNAL; | ||
1380 | } | ||
1381 | |||
1382 | if (time_out < 0) { | ||
1383 | PERROR("Invalid time_out specified.\n"); | ||
1384 | return ME_ERRNO_INVALID_TIMEOUT; | ||
1385 | } | ||
1386 | |||
1387 | ME_SUBDEVICE_ENTER; | ||
1388 | |||
1389 | if (me_circ_buf_space(&instance->circ_buf)) { //The buffer is NOT full. | ||
1390 | *count = me_circ_buf_space(&instance->circ_buf); | ||
1391 | } else { //The buffer is full. | ||
1392 | if (time_out) { | ||
1393 | t = (time_out * HZ) / 1000; | ||
1394 | |||
1395 | if (t == 0) | ||
1396 | t = 1; | ||
1397 | } else { //Max time. | ||
1398 | t = LONG_MAX; | ||
1399 | } | ||
1400 | |||
1401 | *count = 0; | ||
1402 | |||
1403 | j = jiffies; | ||
1404 | |||
1405 | //Only runing process will interrupt this call. Interrupts are when FIFO HF is signaled. | ||
1406 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1407 | ((me_circ_buf_space | ||
1408 | (&instance->circ_buf)) | ||
1409 | || !(inl(instance->status_reg) | ||
1410 | & | ||
1411 | ME6000_AO_STATUS_BIT_FSM)), | ||
1412 | t); | ||
1413 | |||
1414 | if (!(inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM)) { | ||
1415 | PERROR("AO subdevice is not running.\n"); | ||
1416 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
1417 | } else if (signal_pending(current)) { | ||
1418 | PERROR("Wait on values interrupted from signal.\n"); | ||
1419 | instance->status = ao_status_none; | ||
1420 | ao_stop_immediately(instance); | ||
1421 | err = ME_ERRNO_SIGNAL; | ||
1422 | } else if ((jiffies - j) >= t) { | ||
1423 | PERROR("Wait on values timed out.\n"); | ||
1424 | err = ME_ERRNO_TIMEOUT; | ||
1425 | } else { //Uff... all is good. Inform user about empty space. | ||
1426 | *count = me_circ_buf_space(&instance->circ_buf); | ||
1427 | } | ||
1428 | } | ||
1429 | |||
1430 | ME_SUBDEVICE_EXIT; | ||
1431 | |||
1432 | return err; | ||
1433 | } | ||
1434 | |||
1435 | static int me6000_ao_io_stream_start(me_subdevice_t *subdevice, | ||
1436 | struct file *filep, | ||
1437 | int start_mode, int time_out, int flags) | ||
1438 | { | ||
1439 | me6000_ao_subdevice_t *instance; | ||
1440 | int err = ME_ERRNO_SUCCESS; | ||
1441 | unsigned long cpu_flags = 0; | ||
1442 | uint32_t status; | ||
1443 | uint32_t ctrl; | ||
1444 | uint32_t synch; | ||
1445 | int count = 0; | ||
1446 | int circ_buffer_count; | ||
1447 | |||
1448 | unsigned long ref; | ||
1449 | unsigned long delay = 0; | ||
1450 | |||
1451 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
1452 | |||
1453 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1454 | |||
1455 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { | ||
1456 | PERROR("Not a streaming ao.\n"); | ||
1457 | return ME_ERRNO_NOT_SUPPORTED; | ||
1458 | } | ||
1459 | |||
1460 | if (flags & ~ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { | ||
1461 | PERROR("Invalid flags.\n"); | ||
1462 | return ME_ERRNO_INVALID_FLAGS; | ||
1463 | } | ||
1464 | |||
1465 | if (time_out < 0) { | ||
1466 | PERROR("Invalid timeout specified.\n"); | ||
1467 | return ME_ERRNO_INVALID_TIMEOUT; | ||
1468 | } | ||
1469 | |||
1470 | if ((start_mode != ME_START_MODE_BLOCKING) | ||
1471 | && (start_mode != ME_START_MODE_NONBLOCKING)) { | ||
1472 | PERROR("Invalid start mode specified.\n"); | ||
1473 | return ME_ERRNO_INVALID_START_MODE; | ||
1474 | } | ||
1475 | |||
1476 | if (time_out) { | ||
1477 | delay = (time_out * HZ) / 1000; | ||
1478 | if (delay == 0) | ||
1479 | delay = 1; | ||
1480 | } | ||
1481 | |||
1482 | switch (instance->status) { //Checking actual mode. | ||
1483 | case ao_status_stream_configured: | ||
1484 | case ao_status_stream_end: | ||
1485 | //Correct modes! | ||
1486 | break; | ||
1487 | |||
1488 | //The device is in wrong mode. | ||
1489 | case ao_status_none: | ||
1490 | case ao_status_single_configured: | ||
1491 | case ao_status_single_run_wait: | ||
1492 | case ao_status_single_run: | ||
1493 | case ao_status_single_end_wait: | ||
1494 | PERROR | ||
1495 | ("Subdevice must be preinitialize correctly for streaming.\n"); | ||
1496 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
1497 | |||
1498 | case ao_status_stream_fifo_error: | ||
1499 | case ao_status_stream_buffer_error: | ||
1500 | case ao_status_stream_error: | ||
1501 | PDEBUG("Before restart broke stream 'STOP' must be caled.\n"); | ||
1502 | return ME_STATUS_ERROR; | ||
1503 | |||
1504 | case ao_status_stream_run_wait: | ||
1505 | case ao_status_stream_run: | ||
1506 | case ao_status_stream_end_wait: | ||
1507 | PDEBUG("Stream is already working.\n"); | ||
1508 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
1509 | |||
1510 | default: | ||
1511 | instance->status = ao_status_stream_error; | ||
1512 | PERROR_CRITICAL("Status is in wrong state!\n"); | ||
1513 | return ME_ERRNO_INTERNAL; | ||
1514 | |||
1515 | } | ||
1516 | |||
1517 | ME_SUBDEVICE_ENTER; | ||
1518 | |||
1519 | if (instance->mode == ME6000_AO_CONTINOUS) { //Continous | ||
1520 | instance->circ_buf.tail += instance->preloaded_count; | ||
1521 | instance->circ_buf.tail &= instance->circ_buf.mask; | ||
1522 | } | ||
1523 | circ_buffer_count = me_circ_buf_values(&instance->circ_buf); | ||
1524 | |||
1525 | if (!circ_buffer_count && !instance->preloaded_count) { //No values in buffer | ||
1526 | ME_SUBDEVICE_EXIT; | ||
1527 | PERROR("No values in buffer!\n"); | ||
1528 | return ME_ERRNO_LACK_OF_RESOURCES; | ||
1529 | } | ||
1530 | |||
1531 | //Cancel control task | ||
1532 | PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); | ||
1533 | instance->ao_control_task_flag = 0; | ||
1534 | cancel_delayed_work(&instance->ao_control_task); | ||
1535 | |||
1536 | //Stop device | ||
1537 | err = ao_stop_immediately(instance); | ||
1538 | if (err) { | ||
1539 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
1540 | ME_SUBDEVICE_EXIT; | ||
1541 | |||
1542 | return ME_ERRNO_SUBDEVICE_BUSY; | ||
1543 | } | ||
1544 | //Set values for single_read() | ||
1545 | instance->single_value = ME6000_AO_MAX_DATA + 1; | ||
1546 | instance->single_value_in_fifo = ME6000_AO_MAX_DATA + 1; | ||
1547 | |||
1548 | //Setting stop points | ||
1549 | if (instance->stop_mode == ME6000_AO_SCAN_STOP_MODE) { | ||
1550 | instance->stop_data_count = | ||
1551 | instance->stop_count * circ_buffer_count; | ||
1552 | } else { | ||
1553 | instance->stop_data_count = instance->stop_count; | ||
1554 | } | ||
1555 | |||
1556 | if ((instance->stop_data_count != 0) | ||
1557 | && (instance->stop_data_count < circ_buffer_count)) { | ||
1558 | PERROR("More data in buffer than previously set limit!\n"); | ||
1559 | } | ||
1560 | |||
1561 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1562 | ctrl = inl(instance->ctrl_reg); | ||
1563 | //Check FIFO | ||
1564 | 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 | ||
1565 | PINFO("Enableing FIFO.\n"); | ||
1566 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; | ||
1567 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
1568 | |||
1569 | instance->preloaded_count = 0; | ||
1570 | instance->data_count = 0; | ||
1571 | } else { //Block IRQ | ||
1572 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
1573 | } | ||
1574 | outl(ctrl, instance->ctrl_reg); | ||
1575 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1576 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1577 | |||
1578 | //Reset interrupt latch | ||
1579 | inl(instance->irq_reset_reg); | ||
1580 | |||
1581 | //Fill FIFO <= Generaly this should be done by user pre-load call but this is second place to do it. | ||
1582 | status = inl(instance->status_reg); | ||
1583 | if (!(status & ME6000_AO_STATUS_BIT_EF)) { //FIFO empty | ||
1584 | if (instance->stop_data_count != 0) { | ||
1585 | count = ME6000_AO_FIFO_COUNT; | ||
1586 | } else { | ||
1587 | count = | ||
1588 | (ME6000_AO_FIFO_COUNT < | ||
1589 | instance-> | ||
1590 | stop_data_count) ? ME6000_AO_FIFO_COUNT : | ||
1591 | instance->stop_data_count; | ||
1592 | } | ||
1593 | |||
1594 | //Copy data | ||
1595 | count = | ||
1596 | ao_write_data(instance, count, instance->preloaded_count); | ||
1597 | |||
1598 | if (count < 0) { //This should never happend! | ||
1599 | PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); | ||
1600 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
1601 | cpu_flags); | ||
1602 | ME_SUBDEVICE_EXIT; | ||
1603 | return ME_ERRNO_INTERNAL; | ||
1604 | } | ||
1605 | } | ||
1606 | //Set pre-load features. | ||
1607 | spin_lock(instance->preload_reg_lock); | ||
1608 | synch = inl(instance->preload_reg); | ||
1609 | synch &= | ||
1610 | ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance-> | ||
1611 | ao_idx); | ||
1612 | synch |= | ||
1613 | (instance->start_mode & ~ME6000_AO_EXT_TRIG) << instance->ao_idx; | ||
1614 | outl(synch, instance->preload_reg); | ||
1615 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1616 | instance->preload_reg - instance->reg_base, synch); | ||
1617 | spin_unlock(instance->preload_reg_lock); | ||
1618 | |||
1619 | //Default count is '0' | ||
1620 | if (instance->mode == ME6000_AO_CONTINOUS) { //Continous | ||
1621 | instance->preloaded_count = 0; | ||
1622 | instance->circ_buf.tail += count; | ||
1623 | instance->circ_buf.tail &= instance->circ_buf.mask; | ||
1624 | } else { //Wraparound | ||
1625 | instance->preloaded_count += count; | ||
1626 | instance->data_count += count; | ||
1627 | |||
1628 | //Special case: Infinite wraparound with less than FIFO datas always should runs in hardware mode. | ||
1629 | if ((instance->stop_mode == ME6000_AO_INF_STOP_MODE) | ||
1630 | && (circ_buffer_count <= ME6000_AO_FIFO_COUNT)) { //Change to hardware wraparound | ||
1631 | PDEBUG | ||
1632 | ("Changeing mode from software wraparound to hardware wraparound.\n"); | ||
1633 | //Copy all data | ||
1634 | count = | ||
1635 | ao_write_data(instance, circ_buffer_count, | ||
1636 | instance->preloaded_count); | ||
1637 | ctrl &= ~ME6000_AO_CTRL_MODE_MASK; | ||
1638 | ctrl |= ME6000_AO_MODE_WRAPAROUND; | ||
1639 | } | ||
1640 | |||
1641 | if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. | ||
1642 | instance->preloaded_count = 0; | ||
1643 | } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! | ||
1644 | PERROR_CRITICAL | ||
1645 | ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); | ||
1646 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
1647 | cpu_flags); | ||
1648 | ME_SUBDEVICE_EXIT; | ||
1649 | return ME_ERRNO_INTERNAL; | ||
1650 | } | ||
1651 | } | ||
1652 | |||
1653 | //Set status to 'wait for start' | ||
1654 | instance->status = ao_status_stream_run_wait; | ||
1655 | |||
1656 | status = inl(instance->status_reg); | ||
1657 | //Start state machine and interrupts | ||
1658 | PINFO("<%s:%d> Start state machine.\n", __func__, __LINE__); | ||
1659 | ctrl &= ~(ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP); | ||
1660 | if (instance->start_mode == ME6000_AO_EXT_TRIG) { | ||
1661 | PDEBUG("DIGITAL TRIGGER\n"); | ||
1662 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; | ||
1663 | } | ||
1664 | if (!(status & ME6000_AO_STATUS_BIT_HF)) { //More than half! | ||
1665 | 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 | ||
1666 | PINFO("<%s:%d> Start interrupts.\n", __func__, | ||
1667 | __LINE__); | ||
1668 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
1669 | } | ||
1670 | } | ||
1671 | outl(ctrl, instance->ctrl_reg); | ||
1672 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
1673 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
1674 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
1675 | |||
1676 | //Trigger output | ||
1677 | PINFO("<%s> start mode= 0x%x %s\n", __func__, instance->start_mode, | ||
1678 | (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) ? "SYNCHRONOUS" : | ||
1679 | ""); | ||
1680 | if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs | ||
1681 | spin_lock(instance->preload_reg_lock); | ||
1682 | synch = inl(instance->preload_reg); | ||
1683 | //Add channel to start list | ||
1684 | outl(synch | (ME6000_AO_SYNC_HOLD << instance->ao_idx), | ||
1685 | instance->preload_reg); | ||
1686 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1687 | instance->reg_base, | ||
1688 | instance->preload_reg - instance->reg_base, | ||
1689 | synch | (ME6000_AO_SYNC_HOLD << instance->ao_idx)); | ||
1690 | |||
1691 | //Fire | ||
1692 | PINFO | ||
1693 | ("Fired all software synchronous outputs by software trigger.\n"); | ||
1694 | outl(0x8000, instance->single_reg); | ||
1695 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1696 | instance->reg_base, | ||
1697 | instance->single_reg - instance->reg_base, 0x8000); | ||
1698 | |||
1699 | //Restore save settings | ||
1700 | outl(synch, instance->preload_reg); | ||
1701 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1702 | instance->reg_base, | ||
1703 | instance->preload_reg - instance->reg_base, synch); | ||
1704 | spin_unlock(instance->preload_reg_lock); | ||
1705 | } else if (!instance->start_mode) { //Trigger outputs | ||
1706 | /* | ||
1707 | spin_lock(instance->preload_reg_lock); | ||
1708 | synch = inl(instance->preload_reg); | ||
1709 | //Remove channel from start list | ||
1710 | outl(synch & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); | ||
1711 | 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)); | ||
1712 | */ | ||
1713 | //Fire | ||
1714 | PINFO("Software trigger.\n"); | ||
1715 | outl(0x8000, instance->single_reg); | ||
1716 | PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1717 | instance->reg_base, | ||
1718 | instance->single_reg - instance->reg_base, 0x8000); | ||
1719 | |||
1720 | /* | ||
1721 | //Restore save settings | ||
1722 | outl(synch, instance->preload_reg); | ||
1723 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch); | ||
1724 | spin_unlock(instance->preload_reg_lock); | ||
1725 | */ | ||
1726 | } | ||
1727 | // Set control task's timeout | ||
1728 | instance->timeout.delay = delay; | ||
1729 | instance->timeout.start_time = jiffies; | ||
1730 | |||
1731 | if (status & ME6000_AO_STATUS_BIT_HF) { //Less than half but not empty! | ||
1732 | PINFO("Less than half.\n"); | ||
1733 | if (instance->stop_data_count == 0) { | ||
1734 | count = ME6000_AO_FIFO_COUNT / 2; | ||
1735 | } else { | ||
1736 | count = | ||
1737 | ((ME6000_AO_FIFO_COUNT / 2) < | ||
1738 | instance->stop_data_count) ? ME6000_AO_FIFO_COUNT / | ||
1739 | 2 : instance->stop_data_count; | ||
1740 | } | ||
1741 | |||
1742 | //Copy data | ||
1743 | count = | ||
1744 | ao_write_data(instance, count, instance->preloaded_count); | ||
1745 | |||
1746 | if (count < 0) { //This should never happend! | ||
1747 | PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); | ||
1748 | ME_SUBDEVICE_EXIT; | ||
1749 | return ME_ERRNO_INTERNAL; | ||
1750 | } | ||
1751 | |||
1752 | if (instance->mode == ME6000_AO_CONTINOUS) { //Continous | ||
1753 | instance->circ_buf.tail += count; | ||
1754 | instance->circ_buf.tail &= instance->circ_buf.mask; | ||
1755 | } else { //Wraparound | ||
1756 | instance->data_count += count; | ||
1757 | instance->preloaded_count += count; | ||
1758 | |||
1759 | if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. | ||
1760 | instance->preloaded_count = 0; | ||
1761 | } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! | ||
1762 | PERROR_CRITICAL | ||
1763 | ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); | ||
1764 | ME_SUBDEVICE_EXIT; | ||
1765 | return ME_ERRNO_INTERNAL; | ||
1766 | } | ||
1767 | } | ||
1768 | |||
1769 | status = inl(instance->status_reg); | ||
1770 | if (!(status & ME6000_AO_STATUS_BIT_HF)) { //More than half! | ||
1771 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
1772 | PINFO("<%s:%d> Start interrupts.\n", __func__, | ||
1773 | __LINE__); | ||
1774 | ctrl = inl(instance->ctrl_reg); | ||
1775 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
1776 | outl(ctrl, instance->ctrl_reg); | ||
1777 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1778 | instance->reg_base, | ||
1779 | instance->ctrl_reg - instance->reg_base, | ||
1780 | ctrl); | ||
1781 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
1782 | cpu_flags); | ||
1783 | } | ||
1784 | } | ||
1785 | //Special case: Limited wraparound with less than HALF FIFO datas need work around to generate first interrupt. | ||
1786 | if ((instance->stop_mode != ME6000_AO_INF_STOP_MODE) | ||
1787 | && (instance->mode == ME6000_AO_SW_WRAP_MODE) | ||
1788 | && (circ_buffer_count <= (ME6000_AO_FIFO_COUNT / 2))) { //Put more data to FIFO | ||
1789 | PINFO("Limited wraparound with less than HALF FIFO datas.\n"); | ||
1790 | if (instance->preloaded_count) { //This should never happend! | ||
1791 | PERROR_CRITICAL | ||
1792 | ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); | ||
1793 | ME_SUBDEVICE_EXIT; | ||
1794 | return ME_ERRNO_INTERNAL; | ||
1795 | } | ||
1796 | |||
1797 | while (instance->stop_data_count > instance->data_count) { //Maximum data not set jet. | ||
1798 | //Copy to buffer | ||
1799 | if (circ_buffer_count != ao_write_data(instance, circ_buffer_count, 0)) { //This should never happend! | ||
1800 | PERROR_CRITICAL | ||
1801 | ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); | ||
1802 | ME_SUBDEVICE_EXIT; | ||
1803 | return ME_ERRNO_INTERNAL; | ||
1804 | } | ||
1805 | instance->data_count += circ_buffer_count; | ||
1806 | |||
1807 | if (!((status = inl(instance->status_reg)) & ME6000_AO_STATUS_BIT_HF)) { //FIFO is more than half. Enable IRQ and end copy. | ||
1808 | //Reset interrupt latch | ||
1809 | inl(instance->irq_reset_reg); | ||
1810 | |||
1811 | spin_lock_irqsave(&instance->subdevice_lock, | ||
1812 | cpu_flags); | ||
1813 | PINFO("<%s:%d> Start interrupts.\n", | ||
1814 | __func__, __LINE__); | ||
1815 | ctrl = inl(instance->ctrl_reg); | ||
1816 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
1817 | outl(ctrl, instance->ctrl_reg); | ||
1818 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
1819 | instance->reg_base, | ||
1820 | instance->ctrl_reg - | ||
1821 | instance->reg_base, ctrl); | ||
1822 | spin_unlock_irqrestore(&instance-> | ||
1823 | subdevice_lock, | ||
1824 | cpu_flags); | ||
1825 | break; | ||
1826 | } | ||
1827 | } | ||
1828 | } | ||
1829 | // Schedule control task | ||
1830 | instance->ao_control_task_flag = 1; | ||
1831 | queue_delayed_work(instance->me6000_workqueue, | ||
1832 | &instance->ao_control_task, 1); | ||
1833 | |||
1834 | if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start. | ||
1835 | ref = jiffies; | ||
1836 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
1837 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1838 | (instance->status != | ||
1839 | ao_status_stream_run_wait), | ||
1840 | (delay) ? delay + | ||
1841 | 1 : LONG_MAX); | ||
1842 | |||
1843 | if ((instance->status != ao_status_stream_run) | ||
1844 | && (instance->status != ao_status_stream_end)) { | ||
1845 | PDEBUG("Starting stream canceled. %d\n", | ||
1846 | instance->status); | ||
1847 | err = ME_ERRNO_CANCELLED; | ||
1848 | } | ||
1849 | |||
1850 | if (signal_pending(current)) { | ||
1851 | PERROR("Wait on start of state machine interrupted.\n"); | ||
1852 | instance->status = ao_status_none; | ||
1853 | ao_stop_immediately(instance); | ||
1854 | err = ME_ERRNO_SIGNAL; | ||
1855 | } | ||
1856 | |||
1857 | if ((delay) && ((jiffies - ref) >= delay)) { | ||
1858 | if (instance->status != ao_status_stream_run) { | ||
1859 | if (instance->status == ao_status_stream_end) { | ||
1860 | PDEBUG("Timeout reached.\n"); | ||
1861 | } else if ((jiffies - ref) > delay) { | ||
1862 | PERROR | ||
1863 | ("Timeout reached. Not handled by control task!\n"); | ||
1864 | ao_stop_immediately(instance); | ||
1865 | } else { | ||
1866 | PERROR | ||
1867 | ("Timeout reached. Signal come but status is strange: %d\n", | ||
1868 | instance->status); | ||
1869 | ao_stop_immediately(instance); | ||
1870 | } | ||
1871 | |||
1872 | instance->ao_control_task_flag = 0; | ||
1873 | cancel_delayed_work(&instance->ao_control_task); | ||
1874 | instance->status = ao_status_stream_end; | ||
1875 | err = ME_ERRNO_TIMEOUT; | ||
1876 | } | ||
1877 | } | ||
1878 | } | ||
1879 | |||
1880 | ME_SUBDEVICE_EXIT; | ||
1881 | return err; | ||
1882 | } | ||
1883 | |||
1884 | static int me6000_ao_io_stream_status(me_subdevice_t *subdevice, | ||
1885 | struct file *filep, | ||
1886 | int wait, | ||
1887 | int *status, int *values, int flags) | ||
1888 | { | ||
1889 | me6000_ao_subdevice_t *instance; | ||
1890 | int err = ME_ERRNO_SUCCESS; | ||
1891 | |||
1892 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
1893 | |||
1894 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1895 | |||
1896 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { | ||
1897 | PERROR("Not a streaming ao.\n"); | ||
1898 | return ME_ERRNO_NOT_SUPPORTED; | ||
1899 | } | ||
1900 | |||
1901 | if (flags) { | ||
1902 | PERROR("Invalid flag specified.\n"); | ||
1903 | return ME_ERRNO_INVALID_FLAGS; | ||
1904 | } | ||
1905 | |||
1906 | if ((wait != ME_WAIT_NONE) && (wait != ME_WAIT_IDLE)) { | ||
1907 | PERROR("Invalid wait argument specified.\n"); | ||
1908 | *status = ME_STATUS_INVALID; | ||
1909 | return ME_ERRNO_INVALID_WAIT; | ||
1910 | } | ||
1911 | |||
1912 | ME_SUBDEVICE_ENTER; | ||
1913 | |||
1914 | switch (instance->status) { | ||
1915 | case ao_status_single_configured: | ||
1916 | case ao_status_single_end: | ||
1917 | case ao_status_stream_configured: | ||
1918 | case ao_status_stream_end: | ||
1919 | case ao_status_stream_fifo_error: | ||
1920 | case ao_status_stream_buffer_error: | ||
1921 | case ao_status_stream_error: | ||
1922 | *status = ME_STATUS_IDLE; | ||
1923 | break; | ||
1924 | |||
1925 | case ao_status_single_run_wait: | ||
1926 | case ao_status_single_run: | ||
1927 | case ao_status_single_end_wait: | ||
1928 | case ao_status_stream_run_wait: | ||
1929 | case ao_status_stream_run: | ||
1930 | case ao_status_stream_end_wait: | ||
1931 | *status = ME_STATUS_BUSY; | ||
1932 | break; | ||
1933 | |||
1934 | case ao_status_none: | ||
1935 | default: | ||
1936 | *status = | ||
1937 | (inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM) ? | ||
1938 | ME_STATUS_BUSY : ME_STATUS_IDLE; | ||
1939 | break; | ||
1940 | } | ||
1941 | |||
1942 | if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) { | ||
1943 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
1944 | wait_event_interruptible_timeout(instance->wait_queue, | ||
1945 | ((instance->status != | ||
1946 | ao_status_single_run_wait) | ||
1947 | && (instance->status != | ||
1948 | ao_status_single_run) | ||
1949 | && (instance->status != | ||
1950 | ao_status_single_end_wait) | ||
1951 | && (instance->status != | ||
1952 | ao_status_stream_run_wait) | ||
1953 | && (instance->status != | ||
1954 | ao_status_stream_run) | ||
1955 | && (instance->status != | ||
1956 | ao_status_stream_end_wait)), | ||
1957 | LONG_MAX); | ||
1958 | |||
1959 | if (instance->status != ao_status_stream_end) { | ||
1960 | PDEBUG("Wait for IDLE canceled. %d\n", | ||
1961 | instance->status); | ||
1962 | err = ME_ERRNO_CANCELLED; | ||
1963 | } | ||
1964 | |||
1965 | if (signal_pending(current)) { | ||
1966 | PERROR("Wait for IDLE interrupted.\n"); | ||
1967 | instance->status = ao_status_none; | ||
1968 | ao_stop_immediately(instance); | ||
1969 | err = ME_ERRNO_SIGNAL; | ||
1970 | } | ||
1971 | |||
1972 | *status = ME_STATUS_IDLE; | ||
1973 | } | ||
1974 | |||
1975 | *values = me_circ_buf_space(&instance->circ_buf); | ||
1976 | |||
1977 | ME_SUBDEVICE_EXIT; | ||
1978 | |||
1979 | return err; | ||
1980 | } | ||
1981 | |||
1982 | static int me6000_ao_io_stream_stop(me_subdevice_t *subdevice, | ||
1983 | struct file *filep, | ||
1984 | int stop_mode, int flags) | ||
1985 | { /// @note Stop work and empty buffer and FIFO | ||
1986 | int err = ME_ERRNO_SUCCESS; | ||
1987 | me6000_ao_subdevice_t *instance; | ||
1988 | unsigned long cpu_flags; | ||
1989 | volatile uint32_t ctrl; | ||
1990 | |||
1991 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
1992 | |||
1993 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
1994 | |||
1995 | if (flags & ~ME_IO_STREAM_STOP_PRESERVE_BUFFERS) { | ||
1996 | PERROR("Invalid flag specified.\n"); | ||
1997 | return ME_ERRNO_INVALID_FLAGS; | ||
1998 | } | ||
1999 | |||
2000 | if ((stop_mode != ME_STOP_MODE_IMMEDIATE) | ||
2001 | && (stop_mode != ME_STOP_MODE_LAST_VALUE)) { | ||
2002 | PERROR("Invalid stop mode specified.\n"); | ||
2003 | return ME_ERRNO_INVALID_STOP_MODE; | ||
2004 | } | ||
2005 | |||
2006 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { | ||
2007 | PERROR("Not a streaming ao.\n"); | ||
2008 | return ME_ERRNO_NOT_SUPPORTED; | ||
2009 | } | ||
2010 | |||
2011 | if (instance->status < ao_status_stream_configured) { | ||
2012 | //There is nothing to stop! | ||
2013 | PERROR("Subdevice not in streaming mode. %d\n", | ||
2014 | instance->status); | ||
2015 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
2016 | } | ||
2017 | |||
2018 | ME_SUBDEVICE_ENTER; | ||
2019 | |||
2020 | //Mark as stopping. => Software stop. | ||
2021 | instance->status = ao_status_stream_end_wait; | ||
2022 | |||
2023 | if (stop_mode == ME_STOP_MODE_IMMEDIATE) { //Stopped now! | ||
2024 | err = ao_stop_immediately(instance); | ||
2025 | } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { | ||
2026 | ctrl = inl(instance->ctrl_reg) & ME6000_AO_CTRL_MODE_MASK; | ||
2027 | if (ctrl == ME6000_AO_MODE_WRAPAROUND) { //Hardware wraparound => Hardware stop. | ||
2028 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2029 | ctrl = inl(instance->ctrl_reg); | ||
2030 | ctrl |= ME6000_AO_CTRL_BIT_STOP; | ||
2031 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2032 | outl(ctrl, instance->ctrl_reg); | ||
2033 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2034 | instance->reg_base, | ||
2035 | instance->ctrl_reg - instance->reg_base, | ||
2036 | ctrl); | ||
2037 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
2038 | cpu_flags); | ||
2039 | |||
2040 | //Reset interrupt latch | ||
2041 | inl(instance->irq_reset_reg); | ||
2042 | } | ||
2043 | //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. | ||
2044 | wait_event_interruptible_timeout(instance->wait_queue, | ||
2045 | (instance->status != | ||
2046 | ao_status_stream_end_wait), | ||
2047 | LONG_MAX); | ||
2048 | |||
2049 | if (instance->status != ao_status_stream_end) { | ||
2050 | PDEBUG("Stopping stream canceled.\n"); | ||
2051 | err = ME_ERRNO_CANCELLED; | ||
2052 | } | ||
2053 | |||
2054 | if (signal_pending(current)) { | ||
2055 | PERROR("Stopping stream interrupted.\n"); | ||
2056 | instance->status = ao_status_none; | ||
2057 | ao_stop_immediately(instance); | ||
2058 | err = ME_ERRNO_SIGNAL; | ||
2059 | } | ||
2060 | } | ||
2061 | |||
2062 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2063 | ctrl = inl(instance->ctrl_reg); | ||
2064 | ctrl |= ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
2065 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2066 | if (!flags) { //Reset FIFO | ||
2067 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_FIFO; | ||
2068 | } | ||
2069 | outl(ctrl, instance->ctrl_reg); | ||
2070 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
2071 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2072 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
2073 | |||
2074 | //Reset interrupt latch | ||
2075 | inl(instance->irq_reset_reg); | ||
2076 | |||
2077 | if (!flags) { //Reset software buffer | ||
2078 | instance->circ_buf.head = 0; | ||
2079 | instance->circ_buf.tail = 0; | ||
2080 | instance->preloaded_count = 0; | ||
2081 | instance->data_count = 0; | ||
2082 | } | ||
2083 | |||
2084 | ME_SUBDEVICE_EXIT; | ||
2085 | |||
2086 | return err; | ||
2087 | } | ||
2088 | |||
2089 | static int me6000_ao_io_stream_write(me_subdevice_t *subdevice, | ||
2090 | struct file *filep, | ||
2091 | int write_mode, | ||
2092 | int *values, int *count, int flags) | ||
2093 | { | ||
2094 | int err = ME_ERRNO_SUCCESS; | ||
2095 | me6000_ao_subdevice_t *instance; | ||
2096 | unsigned long cpu_flags = 0; | ||
2097 | uint32_t reg_copy; | ||
2098 | |||
2099 | int copied_from_user = 0; | ||
2100 | int left_to_copy_from_user = *count; | ||
2101 | |||
2102 | int copied_values; | ||
2103 | |||
2104 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
2105 | |||
2106 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
2107 | |||
2108 | //Checking arguments | ||
2109 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { | ||
2110 | PERROR("Not a streaming ao.\n"); | ||
2111 | return ME_ERRNO_NOT_SUPPORTED; | ||
2112 | } | ||
2113 | |||
2114 | if (flags) { | ||
2115 | PERROR("Invalid flag specified.\n"); | ||
2116 | return ME_ERRNO_INVALID_FLAGS; | ||
2117 | } | ||
2118 | |||
2119 | if (*count <= 0) { | ||
2120 | PERROR("Invalid count of values specified.\n"); | ||
2121 | return ME_ERRNO_INVALID_VALUE_COUNT; | ||
2122 | } | ||
2123 | |||
2124 | if (values == NULL) { | ||
2125 | PERROR("Invalid address of values specified.\n"); | ||
2126 | return ME_ERRNO_INVALID_POINTER; | ||
2127 | } | ||
2128 | |||
2129 | if ((instance->status == ao_status_none) || (instance->status == ao_status_single_configured)) { //The device is in single mode. | ||
2130 | PERROR | ||
2131 | ("Subdevice must be preinitialize correctly for streaming.\n"); | ||
2132 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
2133 | } | ||
2134 | |||
2135 | switch (write_mode) { | ||
2136 | case ME_WRITE_MODE_PRELOAD: | ||
2137 | |||
2138 | //Device must be stopped. | ||
2139 | if ((instance->status != ao_status_stream_configured) | ||
2140 | && (instance->status != ao_status_stream_end)) { | ||
2141 | PERROR | ||
2142 | ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); | ||
2143 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
2144 | } | ||
2145 | break; | ||
2146 | case ME_WRITE_MODE_NONBLOCKING: | ||
2147 | case ME_WRITE_MODE_BLOCKING: | ||
2148 | /// @note In blocking mode: When device is not runing and there is not enought space call will blocked up! | ||
2149 | /// @note Some other thread must empty buffer by strating engine. | ||
2150 | break; | ||
2151 | |||
2152 | default: | ||
2153 | PERROR("Invalid write mode specified.\n"); | ||
2154 | return ME_ERRNO_INVALID_WRITE_MODE; | ||
2155 | } | ||
2156 | |||
2157 | if (instance->mode & ME6000_AO_WRAP_MODE) { //Wraparound mode. Device must be stopped. | ||
2158 | if ((instance->status != ao_status_stream_configured) | ||
2159 | && (instance->status != ao_status_stream_end)) { | ||
2160 | PERROR | ||
2161 | ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); | ||
2162 | return ME_ERRNO_INVALID_WRITE_MODE; | ||
2163 | } | ||
2164 | } | ||
2165 | |||
2166 | if ((instance->mode == ME6000_AO_HW_WRAP_MODE) | ||
2167 | && (write_mode != ME_WRITE_MODE_PRELOAD)) { | ||
2168 | /* | ||
2169 | PERROR("Only 'pre-load' write is acceptable in hardware wraparound mode.\n"); | ||
2170 | return ME_ERRNO_PREVIOUS_CONFIG; | ||
2171 | */ | ||
2172 | //This is transparent for user. | ||
2173 | PDEBUG("Changing write_mode to ME_WRITE_MODE_PRELOAD.\n"); | ||
2174 | write_mode = ME_WRITE_MODE_PRELOAD; | ||
2175 | } | ||
2176 | |||
2177 | ME_SUBDEVICE_ENTER; | ||
2178 | |||
2179 | if (write_mode == ME_WRITE_MODE_PRELOAD) { //Init enviroment - preload | ||
2180 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2181 | reg_copy = inl(instance->ctrl_reg); | ||
2182 | //Check FIFO | ||
2183 | if (!(reg_copy & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO not active. Enable it. | ||
2184 | reg_copy |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; | ||
2185 | outl(reg_copy, instance->ctrl_reg); | ||
2186 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2187 | instance->reg_base, | ||
2188 | instance->ctrl_reg - instance->reg_base, | ||
2189 | reg_copy); | ||
2190 | instance->preloaded_count = 0; | ||
2191 | } | ||
2192 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
2193 | } | ||
2194 | |||
2195 | while (1) { | ||
2196 | //Copy to buffer. This step is common for all modes. | ||
2197 | copied_from_user = | ||
2198 | ao_get_data_from_user(instance, left_to_copy_from_user, | ||
2199 | values + (*count - | ||
2200 | left_to_copy_from_user)); | ||
2201 | left_to_copy_from_user -= copied_from_user; | ||
2202 | |||
2203 | reg_copy = inl(instance->status_reg); | ||
2204 | 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. | ||
2205 | PERROR("Broken pipe in write.\n"); | ||
2206 | err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; | ||
2207 | break; | ||
2208 | } | ||
2209 | |||
2210 | 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! | ||
2211 | |||
2212 | // Block interrupts. | ||
2213 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2214 | reg_copy = inl(instance->ctrl_reg); | ||
2215 | reg_copy &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2216 | outl(reg_copy, instance->ctrl_reg); | ||
2217 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2218 | instance->reg_base, | ||
2219 | instance->ctrl_reg - instance->reg_base, | ||
2220 | reg_copy); | ||
2221 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
2222 | cpu_flags); | ||
2223 | |||
2224 | //Fast copy | ||
2225 | copied_values = | ||
2226 | ao_write_data(instance, ME6000_AO_FIFO_COUNT / 2, | ||
2227 | 0); | ||
2228 | if (copied_values > 0) { | ||
2229 | instance->circ_buf.tail += copied_values; | ||
2230 | instance->circ_buf.tail &= | ||
2231 | instance->circ_buf.mask; | ||
2232 | continue; | ||
2233 | } | ||
2234 | //Reset interrupt latch | ||
2235 | inl(instance->irq_reset_reg); | ||
2236 | |||
2237 | // Activate interrupts. | ||
2238 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2239 | reg_copy = inl(instance->ctrl_reg); | ||
2240 | reg_copy |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2241 | outl(reg_copy, instance->ctrl_reg); | ||
2242 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2243 | instance->reg_base, | ||
2244 | instance->ctrl_reg - instance->reg_base, | ||
2245 | reg_copy); | ||
2246 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
2247 | cpu_flags); | ||
2248 | |||
2249 | if (copied_values == 0) { //This was checked and never should happend! | ||
2250 | PERROR_CRITICAL("COPY FINISH WITH 0!\n"); | ||
2251 | } | ||
2252 | |||
2253 | if (copied_values < 0) { //This was checked and never should happend! | ||
2254 | PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); | ||
2255 | instance->status = ao_status_stream_fifo_error; | ||
2256 | err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2257 | break; | ||
2258 | } | ||
2259 | } | ||
2260 | |||
2261 | if (!left_to_copy_from_user) { //All datas were copied. | ||
2262 | break; | ||
2263 | } else { //Not all datas were copied. | ||
2264 | if (instance->mode & ME6000_AO_WRAP_MODE) { //Error too much datas! Wraparound is limited in size! | ||
2265 | PERROR | ||
2266 | ("Too much data for wraparound mode! Exceeded size of %ld.\n", | ||
2267 | ME6000_AO_CIRC_BUF_COUNT - 1); | ||
2268 | err = ME_ERRNO_RING_BUFFER_OVERFLOW; | ||
2269 | break; | ||
2270 | } | ||
2271 | |||
2272 | if (write_mode != ME_WRITE_MODE_BLOCKING) { //Non blocking calls | ||
2273 | break; | ||
2274 | } | ||
2275 | |||
2276 | wait_event_interruptible(instance->wait_queue, | ||
2277 | me_circ_buf_space(&instance-> | ||
2278 | circ_buf)); | ||
2279 | |||
2280 | if (signal_pending(current)) { | ||
2281 | PERROR("Writing interrupted by signal.\n"); | ||
2282 | instance->status = ao_status_none; | ||
2283 | ao_stop_immediately(instance); | ||
2284 | err = ME_ERRNO_SIGNAL; | ||
2285 | break; | ||
2286 | } | ||
2287 | |||
2288 | if (instance->status == ao_status_none) { //Reset | ||
2289 | PERROR("Writing interrupted by reset.\n"); | ||
2290 | err = ME_ERRNO_CANCELLED; | ||
2291 | break; | ||
2292 | } | ||
2293 | } | ||
2294 | } | ||
2295 | |||
2296 | if (write_mode == ME_WRITE_MODE_PRELOAD) { //Copy data to FIFO - preload | ||
2297 | copied_values = | ||
2298 | ao_write_data_pooling(instance, ME6000_AO_FIFO_COUNT, | ||
2299 | instance->preloaded_count); | ||
2300 | instance->preloaded_count += copied_values; | ||
2301 | instance->data_count += copied_values; | ||
2302 | |||
2303 | if ((instance->mode == ME6000_AO_HW_WRAP_MODE) | ||
2304 | && (me_circ_buf_values(&instance->circ_buf) > | ||
2305 | ME6000_AO_FIFO_COUNT)) { | ||
2306 | PERROR | ||
2307 | ("Too much data for hardware wraparound mode! Exceeded size of %d.\n", | ||
2308 | ME6000_AO_FIFO_COUNT); | ||
2309 | err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2310 | } | ||
2311 | } | ||
2312 | |||
2313 | *count = *count - left_to_copy_from_user; | ||
2314 | ME_SUBDEVICE_EXIT; | ||
2315 | |||
2316 | return err; | ||
2317 | } | ||
2318 | |||
2319 | static irqreturn_t me6000_ao_isr(int irq, void *dev_id) | ||
2320 | { | ||
2321 | me6000_ao_subdevice_t *instance = dev_id; | ||
2322 | uint32_t irq_status; | ||
2323 | uint32_t ctrl; | ||
2324 | uint32_t status; | ||
2325 | int count = 0; | ||
2326 | |||
2327 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
2328 | |||
2329 | if (irq != instance->irq) { | ||
2330 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
2331 | return IRQ_NONE; | ||
2332 | } | ||
2333 | |||
2334 | irq_status = inl(instance->irq_status_reg); | ||
2335 | if (!(irq_status & (ME6000_IRQ_STATUS_BIT_AO_HF << instance->ao_idx))) { | ||
2336 | PINFO("%ld Shared interrupt. %s(): ID=%d: status_reg=0x%04X\n", | ||
2337 | jiffies, __func__, instance->ao_idx, irq_status); | ||
2338 | return IRQ_NONE; | ||
2339 | } | ||
2340 | |||
2341 | if (!instance->circ_buf.buf) { | ||
2342 | instance->status = ao_status_stream_error; | ||
2343 | PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n"); | ||
2344 | //Block interrupts. Stop machine. | ||
2345 | ctrl = inl(instance->ctrl_reg); | ||
2346 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2347 | ctrl |= | ||
2348 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP; | ||
2349 | outl(ctrl, instance->ctrl_reg); | ||
2350 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2351 | instance->reg_base, | ||
2352 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2353 | |||
2354 | //Inform user | ||
2355 | wake_up_interruptible_all(&instance->wait_queue); | ||
2356 | return IRQ_HANDLED; | ||
2357 | } | ||
2358 | |||
2359 | status = inl(instance->status_reg); | ||
2360 | if (!(status & ME6000_AO_STATUS_BIT_FSM)) { //Too late. Not working! END? BROKEN PIPE? | ||
2361 | /// @note Error checking was moved to separate task. | ||
2362 | PDEBUG("Interrupt come but ISM is not working!\n"); | ||
2363 | //Block interrupts. Stop machine. | ||
2364 | ctrl = inl(instance->ctrl_reg); | ||
2365 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2366 | ctrl |= | ||
2367 | ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
2368 | outl(ctrl, instance->ctrl_reg); | ||
2369 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2370 | instance->reg_base, | ||
2371 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2372 | |||
2373 | //Reset interrupt latch | ||
2374 | inl(instance->irq_reset_reg); | ||
2375 | |||
2376 | /// @note User notification was also moved to separate task. | ||
2377 | return IRQ_HANDLED; | ||
2378 | } | ||
2379 | //General procedure. Process more datas. | ||
2380 | |||
2381 | #ifdef MEDEBUG_DEBUG | ||
2382 | if (!me_circ_buf_values(&instance->circ_buf)) { //Buffer is empty! | ||
2383 | PDEBUG("Circular buffer empty!\n"); | ||
2384 | } | ||
2385 | #endif | ||
2386 | |||
2387 | //Check FIFO | ||
2388 | if (status & ME6000_AO_STATUS_BIT_HF) { //OK less than half | ||
2389 | |||
2390 | //Block interrupts | ||
2391 | ctrl = inl(instance->ctrl_reg); | ||
2392 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2393 | outl(ctrl, instance->ctrl_reg); | ||
2394 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2395 | instance->reg_base, | ||
2396 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2397 | |||
2398 | do { | ||
2399 | //Calculate how many should be copied. | ||
2400 | count = | ||
2401 | (instance->stop_data_count) ? instance-> | ||
2402 | stop_data_count - | ||
2403 | instance->data_count : ME6000_AO_FIFO_COUNT / 2; | ||
2404 | if (ME6000_AO_FIFO_COUNT / 2 < count) { | ||
2405 | count = ME6000_AO_FIFO_COUNT / 2; | ||
2406 | } | ||
2407 | //Copy data | ||
2408 | if (instance->mode == ME6000_AO_CONTINOUS) { //Continous | ||
2409 | count = ao_write_data(instance, count, 0); | ||
2410 | if (count > 0) { | ||
2411 | instance->circ_buf.tail += count; | ||
2412 | instance->circ_buf.tail &= | ||
2413 | instance->circ_buf.mask; | ||
2414 | instance->data_count += count; | ||
2415 | |||
2416 | if ((instance->status == ao_status_stream_end_wait) && !me_circ_buf_values(&instance->circ_buf)) { //Stoping. Whole buffer was copied. | ||
2417 | break; | ||
2418 | } | ||
2419 | } | ||
2420 | } else if ((instance->mode == ME6000_AO_SW_WRAP_MODE) && ((ctrl & ME6000_AO_CTRL_MODE_MASK) == ME6000_AO_MODE_CONTINUOUS)) { //Wraparound (software) | ||
2421 | if (instance->status == ao_status_stream_end_wait) { //We stoping => Copy to the end of the buffer. | ||
2422 | count = | ||
2423 | ao_write_data(instance, count, 0); | ||
2424 | } else { //Copy in wraparound mode. | ||
2425 | count = | ||
2426 | ao_write_data_wraparound(instance, | ||
2427 | count, | ||
2428 | instance-> | ||
2429 | preloaded_count); | ||
2430 | } | ||
2431 | |||
2432 | if (count > 0) { | ||
2433 | instance->data_count += count; | ||
2434 | instance->preloaded_count += count; | ||
2435 | instance->preloaded_count %= | ||
2436 | me_circ_buf_values(&instance-> | ||
2437 | circ_buf); | ||
2438 | |||
2439 | if ((instance->status == ao_status_stream_end_wait) && !instance->preloaded_count) { //Stoping. Whole buffer was copied. | ||
2440 | break; | ||
2441 | } | ||
2442 | } | ||
2443 | } | ||
2444 | |||
2445 | if ((count <= 0) || (instance->stop_data_count && (instance->stop_data_count <= instance->data_count))) { //End of work. | ||
2446 | break; | ||
2447 | } | ||
2448 | } //Repeat if still is under half fifo | ||
2449 | while ((status = | ||
2450 | inl(instance->status_reg)) & ME6000_AO_STATUS_BIT_HF); | ||
2451 | |||
2452 | //Unblock interrupts | ||
2453 | ctrl = inl(instance->ctrl_reg); | ||
2454 | if (count >= 0) { //Copy was successful. | ||
2455 | if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. No more interrupts. | ||
2456 | PDEBUG("Finishing work. Interrupt disabled.\n"); | ||
2457 | instance->status = ao_status_stream_end_wait; | ||
2458 | } else if (count > 0) { //Normal work. Enable interrupt. | ||
2459 | PDEBUG("Normal work. Enable interrupt.\n"); | ||
2460 | ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; | ||
2461 | } else { //Normal work but there are no more data in buffer. Interrupt blocked. stream_write() will unblock it. | ||
2462 | PDEBUG | ||
2463 | ("No data in software buffer. Interrupt blocked.\n"); | ||
2464 | } | ||
2465 | } else { //Error during copy. | ||
2466 | instance->status = ao_status_stream_fifo_error; | ||
2467 | } | ||
2468 | |||
2469 | outl(ctrl, instance->ctrl_reg); | ||
2470 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2471 | instance->reg_base, | ||
2472 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
2473 | } else { //?? more than half | ||
2474 | PDEBUG | ||
2475 | ("Interrupt come but FIFO more than half full! Reset interrupt.\n"); | ||
2476 | } | ||
2477 | |||
2478 | PINFO("ISR: Buffer count: %d.(T:%d H:%d)\n", | ||
2479 | me_circ_buf_values(&instance->circ_buf), instance->circ_buf.tail, | ||
2480 | instance->circ_buf.head); | ||
2481 | PINFO("ISR: Stop count: %d.\n", instance->stop_count); | ||
2482 | PINFO("ISR: Stop data count: %d.\n", instance->stop_data_count); | ||
2483 | PINFO("ISR: Data count: %d.\n", instance->data_count); | ||
2484 | |||
2485 | //Reset interrupt latch | ||
2486 | inl(instance->irq_reset_reg); | ||
2487 | |||
2488 | //Inform user | ||
2489 | wake_up_interruptible_all(&instance->wait_queue); | ||
2490 | |||
2491 | return IRQ_HANDLED; | ||
2492 | } | ||
2493 | |||
2494 | static void me6000_ao_destructor(struct me_subdevice *subdevice) | ||
2495 | { | ||
2496 | me6000_ao_subdevice_t *instance; | ||
2497 | |||
2498 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
2499 | |||
2500 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
2501 | |||
2502 | instance->ao_control_task_flag = 0; | ||
2503 | |||
2504 | // Reset subdevice to asure clean exit. | ||
2505 | me6000_ao_io_reset_subdevice(subdevice, NULL, | ||
2506 | ME_IO_RESET_SUBDEVICE_NO_FLAGS); | ||
2507 | |||
2508 | // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). | ||
2509 | if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. | ||
2510 | set_current_state(TASK_INTERRUPTIBLE); | ||
2511 | schedule_timeout(2); | ||
2512 | } | ||
2513 | |||
2514 | if (instance->fifo & ME6000_AO_HAS_FIFO) { | ||
2515 | if (instance->irq) { | ||
2516 | free_irq(instance->irq, instance); | ||
2517 | instance->irq = 0; | ||
2518 | } | ||
2519 | |||
2520 | if (instance->circ_buf.buf) { | ||
2521 | PDEBUG("free circ_buf = %p size=%d", | ||
2522 | instance->circ_buf.buf, | ||
2523 | PAGE_SHIFT << ME6000_AO_CIRC_BUF_SIZE_ORDER); | ||
2524 | free_pages((unsigned long)instance->circ_buf.buf, | ||
2525 | ME6000_AO_CIRC_BUF_SIZE_ORDER); | ||
2526 | } | ||
2527 | instance->circ_buf.buf = NULL; | ||
2528 | } | ||
2529 | |||
2530 | me_subdevice_deinit(&instance->base); | ||
2531 | kfree(instance); | ||
2532 | } | ||
2533 | |||
2534 | me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base, | ||
2535 | spinlock_t *preload_reg_lock, | ||
2536 | uint32_t *preload_flags, | ||
2537 | uint32_t *triggering_flags, | ||
2538 | int ao_idx, | ||
2539 | int fifo, | ||
2540 | int irq, | ||
2541 | int high_range, | ||
2542 | struct workqueue_struct *me6000_wq) | ||
2543 | { | ||
2544 | me6000_ao_subdevice_t *subdevice; | ||
2545 | int err; | ||
2546 | |||
2547 | PDEBUG("executed ID=%d.\n", ao_idx); | ||
2548 | |||
2549 | /* Allocate memory for subdevice instance */ | ||
2550 | subdevice = kmalloc(sizeof(me6000_ao_subdevice_t), GFP_KERNEL); | ||
2551 | |||
2552 | if (!subdevice) { | ||
2553 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
2554 | return NULL; | ||
2555 | } | ||
2556 | |||
2557 | memset(subdevice, 0, sizeof(me6000_ao_subdevice_t)); | ||
2558 | |||
2559 | /* Initialize subdevice base class */ | ||
2560 | err = me_subdevice_init(&subdevice->base); | ||
2561 | |||
2562 | if (err) { | ||
2563 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
2564 | kfree(subdevice); | ||
2565 | return NULL; | ||
2566 | } | ||
2567 | // Initialize spin locks. | ||
2568 | spin_lock_init(&subdevice->subdevice_lock); | ||
2569 | |||
2570 | subdevice->preload_reg_lock = preload_reg_lock; | ||
2571 | subdevice->preload_flags = preload_flags; | ||
2572 | subdevice->triggering_flags = triggering_flags; | ||
2573 | |||
2574 | /* Store analog output index */ | ||
2575 | subdevice->ao_idx = ao_idx; | ||
2576 | |||
2577 | /* Store if analog output has fifo */ | ||
2578 | subdevice->fifo = fifo; | ||
2579 | |||
2580 | if (subdevice->fifo & ME6000_AO_HAS_FIFO) { | ||
2581 | /* Allocate and initialize circular buffer */ | ||
2582 | subdevice->circ_buf.mask = ME6000_AO_CIRC_BUF_COUNT - 1; | ||
2583 | subdevice->circ_buf.buf = | ||
2584 | (void *)__get_free_pages(GFP_KERNEL, | ||
2585 | ME6000_AO_CIRC_BUF_SIZE_ORDER); | ||
2586 | PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf, | ||
2587 | ME6000_AO_CIRC_BUF_SIZE); | ||
2588 | |||
2589 | if (!subdevice->circ_buf.buf) { | ||
2590 | PERROR | ||
2591 | ("Cannot initialize subdevice base class instance.\n"); | ||
2592 | kfree(subdevice); | ||
2593 | return NULL; | ||
2594 | } | ||
2595 | |||
2596 | memset(subdevice->circ_buf.buf, 0, ME6000_AO_CIRC_BUF_SIZE); | ||
2597 | } else { | ||
2598 | subdevice->circ_buf.mask = 0; | ||
2599 | subdevice->circ_buf.buf = NULL; | ||
2600 | } | ||
2601 | subdevice->circ_buf.head = 0; | ||
2602 | subdevice->circ_buf.tail = 0; | ||
2603 | |||
2604 | subdevice->status = ao_status_none; | ||
2605 | subdevice->ao_control_task_flag = 0; | ||
2606 | subdevice->timeout.delay = 0; | ||
2607 | subdevice->timeout.start_time = jiffies; | ||
2608 | |||
2609 | /* Initialize wait queue */ | ||
2610 | init_waitqueue_head(&subdevice->wait_queue); | ||
2611 | |||
2612 | /* Initialize single value to 0V */ | ||
2613 | subdevice->single_value = 0x8000; | ||
2614 | subdevice->single_value_in_fifo = 0x8000; | ||
2615 | |||
2616 | /* Initialize range boarders */ | ||
2617 | if (high_range) { | ||
2618 | subdevice->min = ME6000_AO_MIN_RANGE_HIGH; | ||
2619 | subdevice->max = ME6000_AO_MAX_RANGE_HIGH; | ||
2620 | } else { | ||
2621 | subdevice->min = ME6000_AO_MIN_RANGE; | ||
2622 | subdevice->max = ME6000_AO_MAX_RANGE; | ||
2623 | } | ||
2624 | |||
2625 | /* Register interrupt service routine */ | ||
2626 | |||
2627 | if (subdevice->fifo & ME6000_AO_HAS_FIFO) { | ||
2628 | subdevice->irq = irq; | ||
2629 | if (request_irq(subdevice->irq, me6000_ao_isr, | ||
2630 | IRQF_DISABLED | IRQF_SHARED, | ||
2631 | ME6000_NAME, subdevice)) { | ||
2632 | PERROR("Cannot get interrupt line.\n"); | ||
2633 | PDEBUG("free circ_buf = %p size=%d", | ||
2634 | subdevice->circ_buf.buf, | ||
2635 | PAGE_SHIFT << ME6000_AO_CIRC_BUF_SIZE_ORDER); | ||
2636 | free_pages((unsigned long)subdevice->circ_buf.buf, | ||
2637 | ME6000_AO_CIRC_BUF_SIZE_ORDER); | ||
2638 | subdevice->circ_buf.buf = NULL; | ||
2639 | kfree(subdevice); | ||
2640 | return NULL; | ||
2641 | } | ||
2642 | PINFO("Registered irq=%d.\n", subdevice->irq); | ||
2643 | } else { | ||
2644 | subdevice->irq = 0; | ||
2645 | } | ||
2646 | |||
2647 | /* Initialize registers */ | ||
2648 | // Only streamed subdevices support interrupts. For the rest this register has no meaning. | ||
2649 | subdevice->irq_status_reg = reg_base + ME6000_AO_IRQ_STATUS_REG; | ||
2650 | subdevice->preload_reg = reg_base + ME6000_AO_PRELOAD_REG; | ||
2651 | |||
2652 | if (ao_idx == 0) { | ||
2653 | subdevice->ctrl_reg = reg_base + ME6000_AO_00_CTRL_REG; | ||
2654 | subdevice->status_reg = reg_base + ME6000_AO_00_STATUS_REG; | ||
2655 | subdevice->fifo_reg = reg_base + ME6000_AO_00_FIFO_REG; | ||
2656 | subdevice->timer_reg = reg_base + ME6000_AO_00_TIMER_REG; | ||
2657 | subdevice->irq_reset_reg = | ||
2658 | reg_base + ME6000_AO_00_IRQ_RESET_REG; | ||
2659 | subdevice->single_reg = reg_base + ME6000_AO_00_SINGLE_REG; | ||
2660 | } else if (ao_idx == 1) { | ||
2661 | subdevice->ctrl_reg = reg_base + ME6000_AO_01_CTRL_REG; | ||
2662 | subdevice->status_reg = reg_base + ME6000_AO_01_STATUS_REG; | ||
2663 | subdevice->fifo_reg = reg_base + ME6000_AO_01_FIFO_REG; | ||
2664 | subdevice->timer_reg = reg_base + ME6000_AO_01_TIMER_REG; | ||
2665 | subdevice->irq_reset_reg = | ||
2666 | reg_base + ME6000_AO_01_IRQ_RESET_REG; | ||
2667 | subdevice->single_reg = reg_base + ME6000_AO_01_SINGLE_REG; | ||
2668 | } else if (ao_idx == 2) { | ||
2669 | subdevice->ctrl_reg = reg_base + ME6000_AO_02_CTRL_REG; | ||
2670 | subdevice->status_reg = reg_base + ME6000_AO_02_STATUS_REG; | ||
2671 | subdevice->fifo_reg = reg_base + ME6000_AO_02_FIFO_REG; | ||
2672 | subdevice->timer_reg = reg_base + ME6000_AO_02_TIMER_REG; | ||
2673 | subdevice->irq_reset_reg = | ||
2674 | reg_base + ME6000_AO_02_IRQ_RESET_REG; | ||
2675 | subdevice->single_reg = reg_base + ME6000_AO_02_SINGLE_REG; | ||
2676 | } else if (ao_idx == 3) { | ||
2677 | subdevice->ctrl_reg = reg_base + ME6000_AO_03_CTRL_REG; | ||
2678 | subdevice->status_reg = reg_base + ME6000_AO_03_STATUS_REG; | ||
2679 | subdevice->fifo_reg = reg_base + ME6000_AO_03_FIFO_REG; | ||
2680 | subdevice->timer_reg = reg_base + ME6000_AO_03_TIMER_REG; | ||
2681 | subdevice->irq_reset_reg = | ||
2682 | reg_base + ME6000_AO_03_IRQ_RESET_REG; | ||
2683 | subdevice->single_reg = reg_base + ME6000_AO_03_SINGLE_REG; | ||
2684 | } else { | ||
2685 | subdevice->ctrl_reg = reg_base + ME6000_AO_DUMY; | ||
2686 | subdevice->fifo_reg = reg_base + ME6000_AO_DUMY; | ||
2687 | subdevice->timer_reg = reg_base + ME6000_AO_DUMY; | ||
2688 | subdevice->irq_reset_reg = reg_base + ME6000_AO_DUMY; | ||
2689 | subdevice->single_reg = reg_base + ME6000_AO_DUMY; | ||
2690 | |||
2691 | subdevice->status_reg = reg_base + ME6000_AO_SINGLE_STATUS_REG; | ||
2692 | if (ao_idx == 4) { | ||
2693 | subdevice->single_reg = | ||
2694 | reg_base + ME6000_AO_04_SINGLE_REG; | ||
2695 | } else if (ao_idx == 5) { | ||
2696 | subdevice->single_reg = | ||
2697 | reg_base + ME6000_AO_05_SINGLE_REG; | ||
2698 | } else if (ao_idx == 6) { | ||
2699 | subdevice->single_reg = | ||
2700 | reg_base + ME6000_AO_06_SINGLE_REG; | ||
2701 | } else if (ao_idx == 7) { | ||
2702 | subdevice->single_reg = | ||
2703 | reg_base + ME6000_AO_07_SINGLE_REG; | ||
2704 | } else if (ao_idx == 8) { | ||
2705 | subdevice->single_reg = | ||
2706 | reg_base + ME6000_AO_08_SINGLE_REG; | ||
2707 | } else if (ao_idx == 9) { | ||
2708 | subdevice->single_reg = | ||
2709 | reg_base + ME6000_AO_09_SINGLE_REG; | ||
2710 | } else if (ao_idx == 10) { | ||
2711 | subdevice->single_reg = | ||
2712 | reg_base + ME6000_AO_10_SINGLE_REG; | ||
2713 | } else if (ao_idx == 11) { | ||
2714 | subdevice->single_reg = | ||
2715 | reg_base + ME6000_AO_11_SINGLE_REG; | ||
2716 | } else if (ao_idx == 12) { | ||
2717 | subdevice->single_reg = | ||
2718 | reg_base + ME6000_AO_12_SINGLE_REG; | ||
2719 | } else if (ao_idx == 13) { | ||
2720 | subdevice->single_reg = | ||
2721 | reg_base + ME6000_AO_13_SINGLE_REG; | ||
2722 | } else if (ao_idx == 14) { | ||
2723 | subdevice->single_reg = | ||
2724 | reg_base + ME6000_AO_14_SINGLE_REG; | ||
2725 | } else if (ao_idx == 15) { | ||
2726 | subdevice->single_reg = | ||
2727 | reg_base + ME6000_AO_15_SINGLE_REG; | ||
2728 | } else { | ||
2729 | PERROR_CRITICAL("WRONG SUBDEVICE ID=%d!", ao_idx); | ||
2730 | me_subdevice_deinit((me_subdevice_t *) subdevice); | ||
2731 | if (subdevice->fifo) { | ||
2732 | free_pages((unsigned long)subdevice->circ_buf. | ||
2733 | buf, ME6000_AO_CIRC_BUF_SIZE_ORDER); | ||
2734 | } | ||
2735 | subdevice->circ_buf.buf = NULL; | ||
2736 | kfree(subdevice); | ||
2737 | return NULL; | ||
2738 | } | ||
2739 | } | ||
2740 | #ifdef MEDEBUG_DEBUG_REG | ||
2741 | subdevice->reg_base = reg_base; | ||
2742 | #endif | ||
2743 | |||
2744 | /* Override base class methods. */ | ||
2745 | subdevice->base.me_subdevice_destructor = me6000_ao_destructor; | ||
2746 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
2747 | me6000_ao_io_reset_subdevice; | ||
2748 | subdevice->base.me_subdevice_io_single_config = | ||
2749 | me6000_ao_io_single_config; | ||
2750 | subdevice->base.me_subdevice_io_single_read = me6000_ao_io_single_read; | ||
2751 | subdevice->base.me_subdevice_io_single_write = | ||
2752 | me6000_ao_io_single_write; | ||
2753 | subdevice->base.me_subdevice_io_stream_config = | ||
2754 | me6000_ao_io_stream_config; | ||
2755 | subdevice->base.me_subdevice_io_stream_new_values = | ||
2756 | me6000_ao_io_stream_new_values; | ||
2757 | subdevice->base.me_subdevice_io_stream_write = | ||
2758 | me6000_ao_io_stream_write; | ||
2759 | subdevice->base.me_subdevice_io_stream_start = | ||
2760 | me6000_ao_io_stream_start; | ||
2761 | subdevice->base.me_subdevice_io_stream_status = | ||
2762 | me6000_ao_io_stream_status; | ||
2763 | subdevice->base.me_subdevice_io_stream_stop = me6000_ao_io_stream_stop; | ||
2764 | subdevice->base.me_subdevice_query_number_channels = | ||
2765 | me6000_ao_query_number_channels; | ||
2766 | subdevice->base.me_subdevice_query_subdevice_type = | ||
2767 | me6000_ao_query_subdevice_type; | ||
2768 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
2769 | me6000_ao_query_subdevice_caps; | ||
2770 | subdevice->base.me_subdevice_query_subdevice_caps_args = | ||
2771 | me6000_ao_query_subdevice_caps_args; | ||
2772 | subdevice->base.me_subdevice_query_range_by_min_max = | ||
2773 | me6000_ao_query_range_by_min_max; | ||
2774 | subdevice->base.me_subdevice_query_number_ranges = | ||
2775 | me6000_ao_query_number_ranges; | ||
2776 | subdevice->base.me_subdevice_query_range_info = | ||
2777 | me6000_ao_query_range_info; | ||
2778 | subdevice->base.me_subdevice_query_timer = me6000_ao_query_timer; | ||
2779 | |||
2780 | //prepare work queue and work function | ||
2781 | subdevice->me6000_workqueue = me6000_wq; | ||
2782 | |||
2783 | /* workqueue API changed in kernel 2.6.20 */ | ||
2784 | INIT_DELAYED_WORK(&subdevice->ao_control_task, | ||
2785 | me6000_ao_work_control_task); | ||
2786 | |||
2787 | if (subdevice->fifo) { //Set speed | ||
2788 | outl(ME6000_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg); | ||
2789 | subdevice->hardware_stop_delay = HZ / 10; //100ms | ||
2790 | } | ||
2791 | |||
2792 | return subdevice; | ||
2793 | } | ||
2794 | |||
2795 | /** @brief Stop presentation. Preserve FIFOs. | ||
2796 | * | ||
2797 | * @param instance The subdevice instance (pointer). | ||
2798 | */ | ||
2799 | inline int ao_stop_immediately(me6000_ao_subdevice_t *instance) | ||
2800 | { | ||
2801 | unsigned long cpu_flags; | ||
2802 | uint32_t ctrl; | ||
2803 | int timeout; | ||
2804 | int i; | ||
2805 | uint32_t single_mask; | ||
2806 | |||
2807 | if (instance->ao_idx < ME6000_AO_SINGLE_STATUS_OFFSET) | ||
2808 | single_mask = 0x0000; | ||
2809 | else | ||
2810 | single_mask = 0x0001 << (instance->ao_idx - | ||
2811 | ME6000_AO_SINGLE_STATUS_OFFSET); | ||
2812 | |||
2813 | timeout = | ||
2814 | (instance->hardware_stop_delay > | ||
2815 | (HZ / 10)) ? instance->hardware_stop_delay : HZ / 10; | ||
2816 | for (i = 0; i <= timeout; i++) { | ||
2817 | if (instance->fifo) { | ||
2818 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
2819 | // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! | ||
2820 | ctrl = inl(instance->ctrl_reg); | ||
2821 | ctrl |= | ||
2822 | ME6000_AO_CTRL_BIT_STOP | | ||
2823 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
2824 | ctrl &= | ||
2825 | ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | | ||
2826 | ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
2827 | outl(ctrl, instance->ctrl_reg); | ||
2828 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
2829 | instance->reg_base, | ||
2830 | instance->ctrl_reg - instance->reg_base, | ||
2831 | ctrl); | ||
2832 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
2833 | cpu_flags); | ||
2834 | |||
2835 | if (!(inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM)) { // Exit. | ||
2836 | break; | ||
2837 | } | ||
2838 | } else { | ||
2839 | if (!(inl(instance->status_reg) & single_mask)) { // Exit. | ||
2840 | break; | ||
2841 | } | ||
2842 | } | ||
2843 | |||
2844 | PINFO("<%s> Wait for stop: %d\n", __func__, i); | ||
2845 | |||
2846 | //Still working! | ||
2847 | set_current_state(TASK_INTERRUPTIBLE); | ||
2848 | schedule_timeout(1); | ||
2849 | } | ||
2850 | |||
2851 | if (i > timeout) { | ||
2852 | PERROR_CRITICAL("FSM IS BUSY!\n"); | ||
2853 | return ME_ERRNO_INTERNAL; | ||
2854 | } | ||
2855 | return ME_ERRNO_SUCCESS; | ||
2856 | } | ||
2857 | |||
2858 | /** @brief Copy data from circular buffer to fifo (fast) in wraparound. | ||
2859 | * @note This is time critical function. Checking is done at begining and end only. | ||
2860 | * @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. | ||
2861 | * | ||
2862 | * @param instance The subdevice instance (pointer). | ||
2863 | * @param count Maximum number of copied data. | ||
2864 | * @param start_pos Position of the firs value in buffer. | ||
2865 | * | ||
2866 | * @return On success: Number of copied data. | ||
2867 | * @return On error/success: 0. No datas were copied => no data in buffer. | ||
2868 | * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. | ||
2869 | */ | ||
2870 | inline int ao_write_data_wraparound(me6000_ao_subdevice_t *instance, int count, | ||
2871 | int start_pos) | ||
2872 | { /// @note This is time critical function! | ||
2873 | uint32_t status; | ||
2874 | uint32_t value; | ||
2875 | int pos = | ||
2876 | (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; | ||
2877 | int local_count = count; | ||
2878 | int i = 1; | ||
2879 | |||
2880 | if (count <= 0) { //Wrong count! | ||
2881 | return 0; | ||
2882 | } | ||
2883 | |||
2884 | while (i < local_count) { | ||
2885 | //Get value from buffer | ||
2886 | value = *(instance->circ_buf.buf + pos); | ||
2887 | //Prepare it | ||
2888 | if (instance->ao_idx & 0x1) { | ||
2889 | value <<= 16; | ||
2890 | } | ||
2891 | //Put value to FIFO | ||
2892 | outl(value, instance->fifo_reg); | ||
2893 | //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); | ||
2894 | |||
2895 | pos++; | ||
2896 | pos &= instance->circ_buf.mask; | ||
2897 | if (pos == instance->circ_buf.head) { | ||
2898 | pos = instance->circ_buf.tail; | ||
2899 | } | ||
2900 | i++; | ||
2901 | } | ||
2902 | |||
2903 | status = inl(instance->status_reg); | ||
2904 | if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! | ||
2905 | PERROR("idx=%d FIFO is full before all datas were copied!\n", | ||
2906 | instance->ao_idx); | ||
2907 | return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2908 | } else { //Add last value | ||
2909 | value = *(instance->circ_buf.buf + pos); | ||
2910 | if (instance->ao_idx & 0x1) { | ||
2911 | value <<= 16; | ||
2912 | } | ||
2913 | //Put value to FIFO | ||
2914 | outl(value, instance->fifo_reg); | ||
2915 | //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); | ||
2916 | } | ||
2917 | |||
2918 | PINFO("idx=%d WRAPAROUND LOADED %d values\n", instance->ao_idx, | ||
2919 | local_count); | ||
2920 | return local_count; | ||
2921 | } | ||
2922 | |||
2923 | /** @brief Copy data from software buffer to fifo (fast). | ||
2924 | * @note This is time critical function. Checking is done at begining and end only. | ||
2925 | * @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. | ||
2926 | * | ||
2927 | * @param instance The subdevice instance (pointer). | ||
2928 | * @param count Maximum number of copied data. | ||
2929 | * @param start_pos Position of the firs value in buffer. | ||
2930 | * | ||
2931 | * @return On success: Number of copied data. | ||
2932 | * @return On error/success: 0. No datas were copied => no data in buffer. | ||
2933 | * @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. | ||
2934 | */ | ||
2935 | inline int ao_write_data(me6000_ao_subdevice_t *instance, int count, | ||
2936 | int start_pos) | ||
2937 | { /// @note This is time critical function! | ||
2938 | uint32_t status; | ||
2939 | uint32_t value; | ||
2940 | int pos = | ||
2941 | (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; | ||
2942 | int local_count = count; | ||
2943 | int max_count; | ||
2944 | int i = 1; | ||
2945 | |||
2946 | if (count <= 0) { //Wrong count! | ||
2947 | return 0; | ||
2948 | } | ||
2949 | |||
2950 | max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; | ||
2951 | if (max_count <= 0) { //No data to copy! | ||
2952 | return 0; | ||
2953 | } | ||
2954 | |||
2955 | if (max_count < count) { | ||
2956 | local_count = max_count; | ||
2957 | } | ||
2958 | |||
2959 | while (i < local_count) { | ||
2960 | //Get value from buffer | ||
2961 | value = *(instance->circ_buf.buf + pos); | ||
2962 | //Prepare it | ||
2963 | if (instance->ao_idx & 0x1) { | ||
2964 | value <<= 16; | ||
2965 | } | ||
2966 | //Put value to FIFO | ||
2967 | outl(value, instance->fifo_reg); | ||
2968 | //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); | ||
2969 | |||
2970 | pos++; | ||
2971 | pos &= instance->circ_buf.mask; | ||
2972 | i++; | ||
2973 | } | ||
2974 | |||
2975 | status = inl(instance->status_reg); | ||
2976 | if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! | ||
2977 | PERROR("idx=%d FIFO is full before all datas were copied!\n", | ||
2978 | instance->ao_idx); | ||
2979 | return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; | ||
2980 | } else { //Add last value | ||
2981 | value = *(instance->circ_buf.buf + pos); | ||
2982 | if (instance->ao_idx & 0x1) { | ||
2983 | value <<= 16; | ||
2984 | } | ||
2985 | //Put value to FIFO | ||
2986 | outl(value, instance->fifo_reg); | ||
2987 | //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); | ||
2988 | } | ||
2989 | |||
2990 | PINFO("idx=%d FAST LOADED %d values\n", instance->ao_idx, local_count); | ||
2991 | return local_count; | ||
2992 | } | ||
2993 | |||
2994 | /** @brief Copy data from software buffer to fifo (slow). | ||
2995 | * @note This is slow function that copy all data from buffer to FIFO with full control. | ||
2996 | * | ||
2997 | * @param instance The subdevice instance (pointer). | ||
2998 | * @param count Maximum number of copied data. | ||
2999 | * @param start_pos Position of the firs value in buffer. | ||
3000 | * | ||
3001 | * @return On success: Number of copied values. | ||
3002 | * @return On error/success: 0. FIFO was full at begining. | ||
3003 | * @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW. | ||
3004 | */ | ||
3005 | inline int ao_write_data_pooling(me6000_ao_subdevice_t *instance, int count, | ||
3006 | int start_pos) | ||
3007 | { /// @note This is slow function! | ||
3008 | uint32_t status; | ||
3009 | uint32_t value; | ||
3010 | int pos = | ||
3011 | (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; | ||
3012 | int local_count = count; | ||
3013 | int i; | ||
3014 | int max_count; | ||
3015 | |||
3016 | if (count <= 0) { //Wrong count! | ||
3017 | PERROR("idx=%d SLOW LOADED: Wrong count!\n", instance->ao_idx); | ||
3018 | return 0; | ||
3019 | } | ||
3020 | |||
3021 | max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; | ||
3022 | if (max_count <= 0) { //No data to copy! | ||
3023 | PERROR("idx=%d SLOW LOADED: No data to copy!\n", | ||
3024 | instance->ao_idx); | ||
3025 | return 0; | ||
3026 | } | ||
3027 | |||
3028 | if (max_count < count) { | ||
3029 | local_count = max_count; | ||
3030 | } | ||
3031 | |||
3032 | for (i = 0; i < local_count; i++) { | ||
3033 | status = inl(instance->status_reg); | ||
3034 | if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full! | ||
3035 | return i; | ||
3036 | } | ||
3037 | //Get value from buffer | ||
3038 | value = *(instance->circ_buf.buf + pos); | ||
3039 | //Prepare it | ||
3040 | if (instance->ao_idx & 0x1) { | ||
3041 | value <<= 16; | ||
3042 | } | ||
3043 | //Put value to FIFO | ||
3044 | outl(value, instance->fifo_reg); | ||
3045 | //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); | ||
3046 | |||
3047 | pos++; | ||
3048 | pos &= instance->circ_buf.mask; | ||
3049 | } | ||
3050 | |||
3051 | PINFO("idx=%d SLOW LOADED %d values\n", instance->ao_idx, local_count); | ||
3052 | return local_count; | ||
3053 | } | ||
3054 | |||
3055 | /** @brief Copy data from user space to circular buffer. | ||
3056 | * @param instance The subdevice instance (pointer). | ||
3057 | * @param count Number of datas in user space. | ||
3058 | * @param user_values Buffer's pointer. | ||
3059 | * | ||
3060 | * @return On success: Number of copied values. | ||
3061 | * @return On error: -ME_ERRNO_INTERNAL. | ||
3062 | */ | ||
3063 | inline int ao_get_data_from_user(me6000_ao_subdevice_t *instance, int count, | ||
3064 | int *user_values) | ||
3065 | { | ||
3066 | int i, err; | ||
3067 | int empty_space; | ||
3068 | int copied; | ||
3069 | int value; | ||
3070 | |||
3071 | empty_space = me_circ_buf_space(&instance->circ_buf); | ||
3072 | //We have only this space free. | ||
3073 | copied = (count < empty_space) ? count : empty_space; | ||
3074 | for (i = 0; i < copied; i++) { //Copy from user to buffer | ||
3075 | if ((err = get_user(value, (int *)(user_values + i)))) { | ||
3076 | PERROR | ||
3077 | ("idx=%d BUFFER LOADED: get_user(0x%p) return an error: %d\n", | ||
3078 | instance->ao_idx, user_values + i, err); | ||
3079 | return -ME_ERRNO_INTERNAL; | ||
3080 | } | ||
3081 | /// @note The analog output in me6000 series has size of 16 bits. | ||
3082 | *(instance->circ_buf.buf + instance->circ_buf.head) = | ||
3083 | (uint16_t) value; | ||
3084 | instance->circ_buf.head++; | ||
3085 | instance->circ_buf.head &= instance->circ_buf.mask; | ||
3086 | } | ||
3087 | |||
3088 | PINFO("idx=%d BUFFER LOADED %d values\n", instance->ao_idx, copied); | ||
3089 | return copied; | ||
3090 | } | ||
3091 | |||
3092 | static void me6000_ao_work_control_task(struct work_struct *work) | ||
3093 | { | ||
3094 | me6000_ao_subdevice_t *instance; | ||
3095 | unsigned long cpu_flags = 0; | ||
3096 | uint32_t status; | ||
3097 | uint32_t ctrl; | ||
3098 | uint32_t synch; | ||
3099 | int reschedule = 0; | ||
3100 | int signaling = 0; | ||
3101 | uint32_t single_mask; | ||
3102 | |||
3103 | instance = | ||
3104 | container_of((void *)work, me6000_ao_subdevice_t, ao_control_task); | ||
3105 | PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, | ||
3106 | instance->ao_idx); | ||
3107 | |||
3108 | status = inl(instance->status_reg); | ||
3109 | PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
3110 | instance->status_reg - instance->reg_base, status); | ||
3111 | |||
3112 | /// @note AO_STATUS_BIT_FSM doesn't work as should be for pure single channels (idx>=4) | ||
3113 | // single_mask = (instance->ao_idx-ME6000_AO_SINGLE_STATUS_OFFSET < 0) ? 0x0000 : (0x0001 << (instance->ao_idx-ME6000_AO_SINGLE_STATUS_OFFSET)); | ||
3114 | single_mask = *instance->triggering_flags & (0x1 << instance->ao_idx); | ||
3115 | |||
3116 | switch (instance->status) { // Checking actual mode. | ||
3117 | |||
3118 | // Not configured for work. | ||
3119 | case ao_status_none: | ||
3120 | break; | ||
3121 | |||
3122 | //This are stable modes. No need to do anything. (?) | ||
3123 | case ao_status_single_configured: | ||
3124 | case ao_status_stream_configured: | ||
3125 | case ao_status_stream_fifo_error: | ||
3126 | case ao_status_stream_buffer_error: | ||
3127 | case ao_status_stream_error: | ||
3128 | PERROR("Shouldn't be running!.\n"); | ||
3129 | break; | ||
3130 | |||
3131 | // Single modes | ||
3132 | case ao_status_single_run_wait: | ||
3133 | case ao_status_single_run: | ||
3134 | case ao_status_single_end_wait: | ||
3135 | if (instance->fifo) { // Extra registers. | ||
3136 | if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. | ||
3137 | if (((instance->fifo & ME6000_AO_HAS_FIFO) | ||
3138 | && (!(status & ME6000_AO_STATUS_BIT_EF))) | ||
3139 | || (!(instance->fifo & ME6000_AO_HAS_FIFO))) { // Single is in end state. | ||
3140 | PDEBUG | ||
3141 | ("Single call has been complited.\n"); | ||
3142 | |||
3143 | // Set correct value for single_read(); | ||
3144 | instance->single_value = | ||
3145 | instance->single_value_in_fifo; | ||
3146 | |||
3147 | // Set status as 'ao_status_single_end' | ||
3148 | instance->status = ao_status_single_end; | ||
3149 | |||
3150 | spin_lock(instance->preload_reg_lock); | ||
3151 | if ((single_mask) && (*instance->preload_flags & (ME6000_AO_SYNC_HOLD << instance->ao_idx))) { // This is one of synchronous start channels. Set all as triggered. | ||
3152 | *instance->triggering_flags = | ||
3153 | 0x00000000; | ||
3154 | } else { | ||
3155 | //Set this channel as triggered (none active). | ||
3156 | *instance->triggering_flags &= | ||
3157 | ~(0x1 << instance->ao_idx); | ||
3158 | } | ||
3159 | spin_unlock(instance->preload_reg_lock); | ||
3160 | |||
3161 | // Signal the end. | ||
3162 | signaling = 1; | ||
3163 | // Wait for stop ISM. | ||
3164 | reschedule = 1; | ||
3165 | |||
3166 | break; | ||
3167 | } | ||
3168 | } | ||
3169 | // Check timeout. | ||
3170 | if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout | ||
3171 | PDEBUG("Timeout reached.\n"); | ||
3172 | // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! | ||
3173 | spin_lock_irqsave(&instance->subdevice_lock, | ||
3174 | cpu_flags); | ||
3175 | ctrl = inl(instance->ctrl_reg); | ||
3176 | ctrl |= | ||
3177 | ME6000_AO_CTRL_BIT_STOP | | ||
3178 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3179 | ctrl &= | ||
3180 | ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | | ||
3181 | ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
3182 | ctrl &= | ||
3183 | ~(ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | | ||
3184 | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); | ||
3185 | //Disabling FIFO | ||
3186 | ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_FIFO; | ||
3187 | |||
3188 | outl(ctrl, instance->ctrl_reg); | ||
3189 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3190 | instance->reg_base, | ||
3191 | instance->ctrl_reg - | ||
3192 | instance->reg_base, ctrl); | ||
3193 | spin_unlock_irqrestore(&instance-> | ||
3194 | subdevice_lock, | ||
3195 | cpu_flags); | ||
3196 | |||
3197 | //Reset interrupt latch | ||
3198 | inl(instance->irq_reset_reg); | ||
3199 | |||
3200 | spin_lock(instance->preload_reg_lock); | ||
3201 | //Remove from synchronous start. Block triggering from this output. | ||
3202 | synch = inl(instance->preload_reg); | ||
3203 | synch &= | ||
3204 | ~((ME6000_AO_SYNC_HOLD | | ||
3205 | ME6000_AO_SYNC_EXT_TRIG) << instance-> | ||
3206 | ao_idx); | ||
3207 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO - set to single safe mode | ||
3208 | synch |= | ||
3209 | ME6000_AO_SYNC_HOLD << instance-> | ||
3210 | ao_idx; | ||
3211 | } | ||
3212 | outl(synch, instance->preload_reg); | ||
3213 | PDEBUG_REG | ||
3214 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3215 | instance->reg_base, | ||
3216 | instance->preload_reg - instance->reg_base, | ||
3217 | synch); | ||
3218 | //Set this channel as triggered (none active). | ||
3219 | *instance->triggering_flags &= | ||
3220 | ~(0x1 << instance->ao_idx); | ||
3221 | spin_unlock(instance->preload_reg_lock); | ||
3222 | |||
3223 | // Set correct value for single_read(); | ||
3224 | instance->single_value_in_fifo = | ||
3225 | instance->single_value; | ||
3226 | |||
3227 | instance->status = ao_status_single_end; | ||
3228 | |||
3229 | // Signal the end. | ||
3230 | signaling = 1; | ||
3231 | } | ||
3232 | } else { // No extra registers. | ||
3233 | /* | ||
3234 | if (!(status & single_mask)) | ||
3235 | {// State machine is not working. | ||
3236 | PDEBUG("Single call has been complited.\n"); | ||
3237 | |||
3238 | // Set correct value for single_read(); | ||
3239 | instance->single_value = instance->single_value_in_fifo; | ||
3240 | |||
3241 | // Set status as 'ao_status_single_end' | ||
3242 | instance->status = ao_status_single_end; | ||
3243 | |||
3244 | // Signal the end. | ||
3245 | signaling = 1; | ||
3246 | // Wait for stop ISM. | ||
3247 | reschedule = 1; | ||
3248 | |||
3249 | break; | ||
3250 | } | ||
3251 | */ | ||
3252 | if (!single_mask) { // Was triggered. | ||
3253 | PDEBUG("Single call has been complited.\n"); | ||
3254 | |||
3255 | // Set correct value for single_read(); | ||
3256 | instance->single_value = | ||
3257 | instance->single_value_in_fifo; | ||
3258 | |||
3259 | // Set status as 'ao_status_single_end' | ||
3260 | instance->status = ao_status_single_end; | ||
3261 | |||
3262 | // Signal the end. | ||
3263 | signaling = 1; | ||
3264 | |||
3265 | break; | ||
3266 | } | ||
3267 | // Check timeout. | ||
3268 | if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout | ||
3269 | PDEBUG("Timeout reached.\n"); | ||
3270 | |||
3271 | spin_lock(instance->preload_reg_lock); | ||
3272 | //Remove from synchronous start. Block triggering from this output. | ||
3273 | synch = inl(instance->preload_reg); | ||
3274 | synch &= | ||
3275 | ~(ME6000_AO_SYNC_EXT_TRIG << instance-> | ||
3276 | ao_idx); | ||
3277 | synch |= | ||
3278 | ME6000_AO_SYNC_HOLD << instance->ao_idx; | ||
3279 | |||
3280 | outl(synch, instance->preload_reg); | ||
3281 | PDEBUG_REG | ||
3282 | ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3283 | instance->reg_base, | ||
3284 | instance->preload_reg - instance->reg_base, | ||
3285 | synch); | ||
3286 | //Set this channel as triggered (none active). | ||
3287 | *instance->triggering_flags &= | ||
3288 | ~(0x1 << instance->ao_idx); | ||
3289 | spin_unlock(instance->preload_reg_lock); | ||
3290 | |||
3291 | // Restore old settings. | ||
3292 | PDEBUG("Write old value back to register.\n"); | ||
3293 | outl(instance->single_value, | ||
3294 | instance->single_reg); | ||
3295 | PDEBUG_REG | ||
3296 | ("single_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3297 | instance->reg_base, | ||
3298 | instance->single_reg - instance->reg_base, | ||
3299 | instance->single_value); | ||
3300 | |||
3301 | // Set correct value for single_read(); | ||
3302 | instance->single_value_in_fifo = | ||
3303 | instance->single_value; | ||
3304 | |||
3305 | instance->status = ao_status_single_end; | ||
3306 | |||
3307 | // Signal the end. | ||
3308 | signaling = 1; | ||
3309 | } | ||
3310 | } | ||
3311 | |||
3312 | // Wait for stop. | ||
3313 | reschedule = 1; | ||
3314 | break; | ||
3315 | |||
3316 | case ao_status_stream_end: | ||
3317 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO | ||
3318 | PERROR_CRITICAL | ||
3319 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3320 | instance->status = ao_status_stream_error; | ||
3321 | // Signal the end. | ||
3322 | signaling = 1; | ||
3323 | break; | ||
3324 | } | ||
3325 | case ao_status_single_end: | ||
3326 | if (instance->fifo) { // Extra registers. | ||
3327 | if (status & ME6000_AO_STATUS_BIT_FSM) { // State machine is working but the status is set to end. Force stop. | ||
3328 | |||
3329 | // Wait for stop. | ||
3330 | reschedule = 1; | ||
3331 | } | ||
3332 | |||
3333 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3334 | // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! | ||
3335 | ctrl = inl(instance->ctrl_reg); | ||
3336 | ctrl |= | ||
3337 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | | ||
3338 | ME6000_AO_CTRL_BIT_STOP; | ||
3339 | ctrl &= | ||
3340 | ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | | ||
3341 | ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
3342 | outl(ctrl, instance->ctrl_reg); | ||
3343 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3344 | instance->reg_base, | ||
3345 | instance->ctrl_reg - instance->reg_base, | ||
3346 | ctrl); | ||
3347 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
3348 | cpu_flags); | ||
3349 | |||
3350 | //Reset interrupt latch | ||
3351 | inl(instance->irq_reset_reg); | ||
3352 | } else { // No extra registers. | ||
3353 | /* | ||
3354 | if (status & single_mask) | ||
3355 | {// State machine is working but the status is set to end. Force stop. | ||
3356 | |||
3357 | // Wait for stop. | ||
3358 | reschedule = 1; | ||
3359 | } | ||
3360 | */ | ||
3361 | } | ||
3362 | break; | ||
3363 | |||
3364 | // Stream modes | ||
3365 | case ao_status_stream_run_wait: | ||
3366 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO | ||
3367 | PERROR_CRITICAL | ||
3368 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3369 | instance->status = ao_status_stream_error; | ||
3370 | // Signal the end. | ||
3371 | signaling = 1; | ||
3372 | break; | ||
3373 | } | ||
3374 | |||
3375 | if (status & ME6000_AO_STATUS_BIT_FSM) { // State machine is working. Waiting for start finish. | ||
3376 | instance->status = ao_status_stream_run; | ||
3377 | |||
3378 | // Signal end of this step | ||
3379 | signaling = 1; | ||
3380 | } else { // State machine is not working. | ||
3381 | if (!(status & ME6000_AO_STATUS_BIT_EF)) { // FIFO is empty. Procedure has started and finish already! | ||
3382 | instance->status = ao_status_stream_end; | ||
3383 | |||
3384 | // Signal the end. | ||
3385 | signaling = 1; | ||
3386 | // Wait for stop. | ||
3387 | reschedule = 1; | ||
3388 | break; | ||
3389 | } | ||
3390 | } | ||
3391 | |||
3392 | // Check timeout. | ||
3393 | if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout | ||
3394 | PDEBUG("Timeout reached.\n"); | ||
3395 | // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! | ||
3396 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
3397 | ctrl = inl(instance->ctrl_reg); | ||
3398 | ctrl |= | ||
3399 | ME6000_AO_CTRL_BIT_STOP | | ||
3400 | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; | ||
3401 | ctrl &= | ||
3402 | ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | | ||
3403 | ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); | ||
3404 | outl(ctrl, instance->ctrl_reg); | ||
3405 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3406 | instance->reg_base, | ||
3407 | instance->ctrl_reg - instance->reg_base, | ||
3408 | ctrl); | ||
3409 | spin_unlock_irqrestore(&instance->subdevice_lock, | ||
3410 | cpu_flags); | ||
3411 | |||
3412 | //Reset interrupt latch | ||
3413 | inl(instance->irq_reset_reg); | ||
3414 | |||
3415 | spin_lock(instance->preload_reg_lock); | ||
3416 | //Remove from synchronous start. Block triggering from this output. | ||
3417 | synch = inl(instance->preload_reg); | ||
3418 | synch &= | ||
3419 | ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << | ||
3420 | instance->ao_idx); | ||
3421 | outl(synch, instance->preload_reg); | ||
3422 | PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
3423 | instance->reg_base, | ||
3424 | instance->preload_reg - instance->reg_base, | ||
3425 | synch); | ||
3426 | spin_unlock(instance->preload_reg_lock); | ||
3427 | |||
3428 | instance->status = ao_status_stream_end; | ||
3429 | |||
3430 | // Signal the end. | ||
3431 | signaling = 1; | ||
3432 | } | ||
3433 | // Wait for stop. | ||
3434 | reschedule = 1; | ||
3435 | break; | ||
3436 | |||
3437 | case ao_status_stream_run: | ||
3438 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO | ||
3439 | PERROR_CRITICAL | ||
3440 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3441 | instance->status = ao_status_stream_error; | ||
3442 | // Signal the end. | ||
3443 | signaling = 1; | ||
3444 | break; | ||
3445 | } | ||
3446 | |||
3447 | if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. This is an error. | ||
3448 | // BROKEN PIPE! | ||
3449 | if (!(status & ME6000_AO_STATUS_BIT_EF)) { // FIFO is empty. | ||
3450 | if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. | ||
3451 | if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. Requed data shown. | ||
3452 | PDEBUG | ||
3453 | ("ISM stoped. No data in FIFO. Buffer is not empty.\n"); | ||
3454 | instance->status = | ||
3455 | ao_status_stream_end; | ||
3456 | } else { | ||
3457 | PERROR | ||
3458 | ("Output stream has been broken. ISM stoped. No data in FIFO. Buffer is not empty.\n"); | ||
3459 | instance->status = | ||
3460 | ao_status_stream_buffer_error; | ||
3461 | } | ||
3462 | } else { // Software buffer is empty. | ||
3463 | PDEBUG | ||
3464 | ("ISM stoped. No data in FIFO. Buffer is empty.\n"); | ||
3465 | instance->status = ao_status_stream_end; | ||
3466 | } | ||
3467 | } else { // There are still datas in FIFO. | ||
3468 | if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. | ||
3469 | PERROR | ||
3470 | ("Output stream has been broken. ISM stoped but some data in FIFO and buffer.\n"); | ||
3471 | } else { // Software buffer is empty. | ||
3472 | PERROR | ||
3473 | ("Output stream has been broken. ISM stoped but some data in FIFO. Buffer is empty.\n"); | ||
3474 | } | ||
3475 | instance->status = ao_status_stream_fifo_error; | ||
3476 | |||
3477 | } | ||
3478 | |||
3479 | // Signal the failure. | ||
3480 | signaling = 1; | ||
3481 | break; | ||
3482 | } | ||
3483 | // Wait for stop. | ||
3484 | reschedule = 1; | ||
3485 | break; | ||
3486 | |||
3487 | case ao_status_stream_end_wait: | ||
3488 | if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO | ||
3489 | PERROR_CRITICAL | ||
3490 | ("Streaming on single device! This feature is not implemented in this version!\n"); | ||
3491 | instance->status = ao_status_stream_error; | ||
3492 | // Signal the end. | ||
3493 | signaling = 1; | ||
3494 | break; | ||
3495 | } | ||
3496 | |||
3497 | if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. Waiting for stop finish. | ||
3498 | instance->status = ao_status_stream_end; | ||
3499 | signaling = 1; | ||
3500 | } | ||
3501 | // State machine is working. | ||
3502 | reschedule = 1; | ||
3503 | break; | ||
3504 | |||
3505 | default: | ||
3506 | PERROR_CRITICAL("Status is in wrong state (%d)!\n", | ||
3507 | instance->status); | ||
3508 | instance->status = ao_status_stream_error; | ||
3509 | // Signal the end. | ||
3510 | signaling = 1; | ||
3511 | break; | ||
3512 | |||
3513 | } | ||
3514 | |||
3515 | if (signaling) { //Signal it. | ||
3516 | wake_up_interruptible_all(&instance->wait_queue); | ||
3517 | } | ||
3518 | |||
3519 | if (instance->ao_control_task_flag && reschedule) { // Reschedule task | ||
3520 | queue_delayed_work(instance->me6000_workqueue, | ||
3521 | &instance->ao_control_task, 1); | ||
3522 | } else { | ||
3523 | PINFO("<%s> Ending control task.\n", __func__); | ||
3524 | } | ||
3525 | |||
3526 | } | ||
3527 | |||
3528 | static int me6000_ao_query_range_by_min_max(me_subdevice_t *subdevice, | ||
3529 | int unit, | ||
3530 | int *min, | ||
3531 | int *max, int *maxdata, int *range) | ||
3532 | { | ||
3533 | me6000_ao_subdevice_t *instance; | ||
3534 | |||
3535 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3536 | |||
3537 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3538 | |||
3539 | if ((*max - *min) < 0) { | ||
3540 | PERROR("Invalid minimum and maximum values specified.\n"); | ||
3541 | return ME_ERRNO_INVALID_MIN_MAX; | ||
3542 | } | ||
3543 | |||
3544 | if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { | ||
3545 | if ((*max <= (instance->max + 1000)) && (*min >= instance->min)) { | ||
3546 | *min = instance->min; | ||
3547 | *max = instance->max; | ||
3548 | *maxdata = ME6000_AO_MAX_DATA; | ||
3549 | *range = 0; | ||
3550 | } else { | ||
3551 | PERROR("No matching range available.\n"); | ||
3552 | return ME_ERRNO_NO_RANGE; | ||
3553 | } | ||
3554 | } else { | ||
3555 | PERROR("Invalid physical unit specified.\n"); | ||
3556 | return ME_ERRNO_INVALID_UNIT; | ||
3557 | } | ||
3558 | |||
3559 | return ME_ERRNO_SUCCESS; | ||
3560 | } | ||
3561 | |||
3562 | static int me6000_ao_query_number_ranges(me_subdevice_t *subdevice, | ||
3563 | int unit, int *count) | ||
3564 | { | ||
3565 | me6000_ao_subdevice_t *instance; | ||
3566 | |||
3567 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3568 | |||
3569 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3570 | |||
3571 | if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { | ||
3572 | *count = 1; | ||
3573 | } else { | ||
3574 | *count = 0; | ||
3575 | } | ||
3576 | |||
3577 | return ME_ERRNO_SUCCESS; | ||
3578 | } | ||
3579 | |||
3580 | static int me6000_ao_query_range_info(me_subdevice_t *subdevice, | ||
3581 | int range, | ||
3582 | int *unit, | ||
3583 | int *min, int *max, int *maxdata) | ||
3584 | { | ||
3585 | me6000_ao_subdevice_t *instance; | ||
3586 | |||
3587 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3588 | |||
3589 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3590 | |||
3591 | if (range == 0) { | ||
3592 | *unit = ME_UNIT_VOLT; | ||
3593 | *min = instance->min; | ||
3594 | *max = instance->max; | ||
3595 | *maxdata = ME6000_AO_MAX_DATA; | ||
3596 | } else { | ||
3597 | PERROR("Invalid range number specified.\n"); | ||
3598 | return ME_ERRNO_INVALID_RANGE; | ||
3599 | } | ||
3600 | |||
3601 | return ME_ERRNO_SUCCESS; | ||
3602 | } | ||
3603 | |||
3604 | static int me6000_ao_query_timer(me_subdevice_t *subdevice, | ||
3605 | int timer, | ||
3606 | int *base_frequency, | ||
3607 | long long *min_ticks, long long *max_ticks) | ||
3608 | { | ||
3609 | me6000_ao_subdevice_t *instance; | ||
3610 | |||
3611 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3612 | |||
3613 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3614 | |||
3615 | if (instance->fifo) { //Streaming device. | ||
3616 | *base_frequency = ME6000_AO_BASE_FREQUENCY; | ||
3617 | if (timer == ME_TIMER_ACQ_START) { | ||
3618 | *min_ticks = ME6000_AO_MIN_ACQ_TICKS; | ||
3619 | *max_ticks = ME6000_AO_MAX_ACQ_TICKS; | ||
3620 | } else if (timer == ME_TIMER_CONV_START) { | ||
3621 | *min_ticks = ME6000_AO_MIN_CHAN_TICKS; | ||
3622 | *max_ticks = ME6000_AO_MAX_CHAN_TICKS; | ||
3623 | } | ||
3624 | } else { //Not streaming device! | ||
3625 | *base_frequency = 0; | ||
3626 | *min_ticks = 0; | ||
3627 | *max_ticks = 0; | ||
3628 | } | ||
3629 | |||
3630 | return ME_ERRNO_SUCCESS; | ||
3631 | } | ||
3632 | |||
3633 | static int me6000_ao_query_number_channels(me_subdevice_t *subdevice, | ||
3634 | int *number) | ||
3635 | { | ||
3636 | me6000_ao_subdevice_t *instance; | ||
3637 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3638 | |||
3639 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3640 | |||
3641 | *number = 1; | ||
3642 | return ME_ERRNO_SUCCESS; | ||
3643 | } | ||
3644 | |||
3645 | static int me6000_ao_query_subdevice_type(me_subdevice_t *subdevice, | ||
3646 | int *type, int *subtype) | ||
3647 | { | ||
3648 | me6000_ao_subdevice_t *instance; | ||
3649 | |||
3650 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3651 | |||
3652 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3653 | |||
3654 | *type = ME_TYPE_AO; | ||
3655 | *subtype = | ||
3656 | (instance-> | ||
3657 | fifo & ME6000_AO_HAS_FIFO) ? ME_SUBTYPE_STREAMING : | ||
3658 | ME_SUBTYPE_SINGLE; | ||
3659 | |||
3660 | return ME_ERRNO_SUCCESS; | ||
3661 | } | ||
3662 | |||
3663 | static int me6000_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
3664 | { | ||
3665 | me6000_ao_subdevice_t *instance; | ||
3666 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3667 | |||
3668 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3669 | |||
3670 | *caps = | ||
3671 | ME_CAPS_AO_TRIG_SYNCHRONOUS | ((instance->fifo) ? ME_CAPS_AO_FIFO : | ||
3672 | ME_CAPS_NONE); | ||
3673 | |||
3674 | return ME_ERRNO_SUCCESS; | ||
3675 | } | ||
3676 | |||
3677 | static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, | ||
3678 | int cap, int *args, int count) | ||
3679 | { | ||
3680 | me6000_ao_subdevice_t *instance; | ||
3681 | int err = ME_ERRNO_SUCCESS; | ||
3682 | |||
3683 | instance = (me6000_ao_subdevice_t *) subdevice; | ||
3684 | |||
3685 | PDEBUG("executed. idx=%d\n", instance->ao_idx); | ||
3686 | |||
3687 | if (count != 1) { | ||
3688 | PERROR("Invalid capability argument count.\n"); | ||
3689 | return ME_ERRNO_INVALID_CAP_ARG_COUNT; | ||
3690 | } | ||
3691 | |||
3692 | switch (cap) { | ||
3693 | case ME_CAP_AI_FIFO_SIZE: | ||
3694 | args[0] = (instance->fifo) ? ME6000_AO_FIFO_COUNT : 0; | ||
3695 | break; | ||
3696 | |||
3697 | case ME_CAP_AI_BUFFER_SIZE: | ||
3698 | args[0] = | ||
3699 | (instance->circ_buf.buf) ? ME6000_AO_CIRC_BUF_COUNT : 0; | ||
3700 | break; | ||
3701 | |||
3702 | default: | ||
3703 | PERROR("Invalid capability.\n"); | ||
3704 | err = ME_ERRNO_INVALID_CAP; | ||
3705 | args[0] = 0; | ||
3706 | } | ||
3707 | |||
3708 | return err; | ||
3709 | } | ||
diff --git a/drivers/staging/meilhaus/me6000_ao.h b/drivers/staging/meilhaus/me6000_ao.h deleted file mode 100644 index d86fb29265f5..000000000000 --- a/drivers/staging/meilhaus/me6000_ao.h +++ /dev/null | |||
@@ -1,195 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_ao.h | ||
3 | * | ||
4 | * @brief Meilhaus ME-6000 analog output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME6000_AO_H_ | ||
28 | #define _ME6000_AO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | #include "mecirc_buf.h" | ||
32 | #include "meioctl.h" | ||
33 | |||
34 | #ifdef __KERNEL__ | ||
35 | |||
36 | #define ME6000_AO_MAX_SUBDEVICES 16 | ||
37 | #define ME6000_AO_FIFO_COUNT 8192 | ||
38 | |||
39 | #define ME6000_AO_BASE_FREQUENCY 33000000L | ||
40 | |||
41 | #define ME6000_AO_MIN_ACQ_TICKS 0LL | ||
42 | #define ME6000_AO_MAX_ACQ_TICKS 0LL | ||
43 | |||
44 | #define ME6000_AO_MIN_CHAN_TICKS 66LL | ||
45 | #define ME6000_AO_MAX_CHAN_TICKS 0xFFFFFFFFLL | ||
46 | |||
47 | #define ME6000_AO_MIN_RANGE -10000000 | ||
48 | #define ME6000_AO_MAX_RANGE 9999694 | ||
49 | |||
50 | #define ME6000_AO_MIN_RANGE_HIGH 0 | ||
51 | #define ME6000_AO_MAX_RANGE_HIGH 49999237 | ||
52 | |||
53 | #define ME6000_AO_MAX_DATA 0xFFFF | ||
54 | |||
55 | #ifdef ME_SYNAPSE | ||
56 | # define ME6000_AO_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse | ||
57 | #else | ||
58 | # define ME6000_AO_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB | ||
59 | #endif | ||
60 | #define ME6000_AO_CIRC_BUF_SIZE PAGE_SIZE<<ME6000_AO_CIRC_BUF_SIZE_ORDER // Buffer size in bytes. | ||
61 | |||
62 | # ifdef _CBUFF_32b_t | ||
63 | # define ME6000_AO_CIRC_BUF_COUNT ((ME6000_AO_CIRC_BUF_SIZE) / sizeof(uint32_t)) // Size in values | ||
64 | # else | ||
65 | # define ME6000_AO_CIRC_BUF_COUNT ((ME6000_AO_CIRC_BUF_SIZE) / sizeof(uint16_t)) // Size in values | ||
66 | # endif | ||
67 | |||
68 | # define ME6000_AO_CONTINOUS 0x0 | ||
69 | # define ME6000_AO_WRAP_MODE 0x1 | ||
70 | # define ME6000_AO_HW_MODE 0x2 | ||
71 | |||
72 | # define ME6000_AO_HW_WRAP_MODE (ME6000_AO_WRAP_MODE | ME6000_AO_HW_MODE) | ||
73 | # define ME6000_AO_SW_WRAP_MODE ME6000_AO_WRAP_MODE | ||
74 | |||
75 | # define ME6000_AO_INF_STOP_MODE 0x0 | ||
76 | # define ME6000_AO_ACQ_STOP_MODE 0x1 | ||
77 | # define ME6000_AO_SCAN_STOP_MODE 0x2 | ||
78 | |||
79 | # define ME6000_AO_EXTRA_HARDWARE 0x1 | ||
80 | # define ME6000_AO_HAS_FIFO 0x2 | ||
81 | |||
82 | typedef enum ME6000_AO_STATUS { | ||
83 | ao_status_none = 0, | ||
84 | ao_status_single_configured, | ||
85 | ao_status_single_run_wait, | ||
86 | ao_status_single_run, | ||
87 | ao_status_single_end_wait, | ||
88 | ao_status_single_end, | ||
89 | ao_status_stream_configured, | ||
90 | ao_status_stream_run_wait, | ||
91 | ao_status_stream_run, | ||
92 | ao_status_stream_end_wait, | ||
93 | ao_status_stream_end, | ||
94 | ao_status_stream_fifo_error, | ||
95 | ao_status_stream_buffer_error, | ||
96 | ao_status_stream_error, | ||
97 | ao_status_last | ||
98 | } ME6000_AO_STATUS; | ||
99 | |||
100 | typedef struct me6000_ao_timeout { | ||
101 | unsigned long start_time; | ||
102 | unsigned long delay; | ||
103 | } me6000_ao_timeout_t; | ||
104 | |||
105 | /** | ||
106 | * @brief The ME-6000 analog output subdevice class. | ||
107 | */ | ||
108 | typedef struct me6000_ao_subdevice { | ||
109 | /* Inheritance */ | ||
110 | me_subdevice_t base; /**< The subdevice base class. */ | ||
111 | unsigned int ao_idx; | ||
112 | |||
113 | /* Attributes */ | ||
114 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
115 | spinlock_t *preload_reg_lock; /**< Spin lock to protect preload_reg from concurrent access. */ | ||
116 | |||
117 | uint32_t *preload_flags; | ||
118 | uint32_t *triggering_flags; | ||
119 | |||
120 | /* Hardware feautres */ | ||
121 | unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */ | ||
122 | int fifo; /**< If set this device has a FIFO. */ | ||
123 | |||
124 | //Range | ||
125 | int min; | ||
126 | int max; | ||
127 | |||
128 | int single_value; /**< Mirror of the output value in single mode. */ | ||
129 | int single_value_in_fifo; /**< Mirror of the value written in single mode. */ | ||
130 | uint32_t ctrl_trg; /**< Mirror of the trigger settings. */ | ||
131 | |||
132 | volatile int mode; /**< Flags used for storing SW wraparound setup*/ | ||
133 | int stop_mode; /**< The user defined stop condition flag. */ | ||
134 | unsigned int start_mode; | ||
135 | unsigned int stop_count; /**< The user defined dates presentation end count. */ | ||
136 | unsigned int stop_data_count; /**< The stop presentation count. */ | ||
137 | unsigned int data_count; /**< The real presentation count. */ | ||
138 | unsigned int preloaded_count; /**< The next data addres in buffer. <= for wraparound mode. */ | ||
139 | int hardware_stop_delay; /**< The time that stop can take. This is only to not show hardware bug to user. */ | ||
140 | |||
141 | volatile enum ME6000_AO_STATUS status; /**< The current stream status flag. */ | ||
142 | me6000_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */ | ||
143 | |||
144 | /* Registers *//**< All registers are 32 bits long. */ | ||
145 | unsigned long ctrl_reg; | ||
146 | unsigned long status_reg; | ||
147 | unsigned long fifo_reg; | ||
148 | unsigned long single_reg; | ||
149 | unsigned long timer_reg; | ||
150 | unsigned long irq_status_reg; | ||
151 | unsigned long preload_reg; | ||
152 | unsigned long irq_reset_reg; | ||
153 | #ifdef MEDEBUG_DEBUG_REG | ||
154 | unsigned long reg_base; | ||
155 | #endif | ||
156 | |||
157 | /* Software buffer */ | ||
158 | me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. */ | ||
159 | wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ | ||
160 | |||
161 | struct workqueue_struct *me6000_workqueue; | ||
162 | struct delayed_work ao_control_task; | ||
163 | |||
164 | volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ | ||
165 | |||
166 | } me6000_ao_subdevice_t; | ||
167 | |||
168 | /** | ||
169 | * @brief The constructor to generate a ME-6000 analog output subdevice instance. | ||
170 | * | ||
171 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
172 | * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. | ||
173 | * @param preload_flags Pointer to spin lock protecting the hold&trigger register from concurrent access. | ||
174 | * @param ao_idx Subdevice number. | ||
175 | * @param fifo Flag set if subdevice has hardware FIFO. | ||
176 | * @param irq IRQ number. | ||
177 | * @param high_range Flag set if subdevice has high curren output. | ||
178 | * @param me6000_wq Queue for asynchronous task (1 queue for all subdevice on 1 board). | ||
179 | * | ||
180 | * @return Pointer to new instance on success.\n | ||
181 | * NULL on error. | ||
182 | */ | ||
183 | me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base, | ||
184 | spinlock_t * preload_reg_lock, | ||
185 | uint32_t * preload_flags, | ||
186 | uint32_t * triggering_flags, | ||
187 | int ao_idx, | ||
188 | int fifo, | ||
189 | int irq, | ||
190 | int high_range, | ||
191 | struct workqueue_struct | ||
192 | *me6000_wq); | ||
193 | |||
194 | #endif //__KERNEL__ | ||
195 | #endif //_ME6000_AO_H_ | ||
diff --git a/drivers/staging/meilhaus/me6000_ao_reg.h b/drivers/staging/meilhaus/me6000_ao_reg.h deleted file mode 100644 index eb8f46e1b75b..000000000000 --- a/drivers/staging/meilhaus/me6000_ao_reg.h +++ /dev/null | |||
@@ -1,177 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_ao_reg.h | ||
3 | * | ||
4 | * @brief ME-6000 analog output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME6000_AO_REG_H_ | ||
28 | #define _ME6000_AO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | // AO | ||
33 | #define ME6000_AO_00_CTRL_REG 0x00 // R/W | ||
34 | #define ME6000_AO_00_STATUS_REG 0x04 // R/_ | ||
35 | #define ME6000_AO_00_FIFO_REG 0x08 // _/W | ||
36 | #define ME6000_AO_00_SINGLE_REG 0x0C // R/W | ||
37 | #define ME6000_AO_00_TIMER_REG 0x10 // _/W | ||
38 | |||
39 | #define ME6000_AO_01_CTRL_REG 0x18 // R/W | ||
40 | #define ME6000_AO_01_STATUS_REG 0x1C // R/_ | ||
41 | #define ME6000_AO_01_FIFO_REG 0x20 // _/W | ||
42 | #define ME6000_AO_01_SINGLE_REG 0x24 // R/W | ||
43 | #define ME6000_AO_01_TIMER_REG 0x28 // _/W | ||
44 | |||
45 | #define ME6000_AO_02_CTRL_REG 0x30 // R/W | ||
46 | #define ME6000_AO_02_STATUS_REG 0x34 // R/_ | ||
47 | #define ME6000_AO_02_FIFO_REG 0x38 // _/W | ||
48 | #define ME6000_AO_02_SINGLE_REG 0x3C // R/W | ||
49 | #define ME6000_AO_02_TIMER_REG 0x40 // _/W | ||
50 | |||
51 | #define ME6000_AO_03_CTRL_REG 0x48 // R/W | ||
52 | #define ME6000_AO_03_STATUS_REG 0x4C // R/_ | ||
53 | #define ME6000_AO_03_FIFO_REG 0x50 // _/W | ||
54 | #define ME6000_AO_03_SINGLE_REG 0x54 // R/W | ||
55 | #define ME6000_AO_03_TIMER_REG 0x58 // _/W | ||
56 | |||
57 | #define ME6000_AO_SINGLE_STATUS_REG 0xA4 // R/_ | ||
58 | #define ME6000_AO_SINGLE_STATUS_OFFSET 4 //The first single subdevice => bit 0 in ME6000_AO_SINGLE_STATUS_REG. | ||
59 | |||
60 | #define ME6000_AO_04_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
61 | #define ME6000_AO_04_SINGLE_REG 0x74 // _/W | ||
62 | |||
63 | #define ME6000_AO_05_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
64 | #define ME6000_AO_05_SINGLE_REG 0x78 // _/W | ||
65 | |||
66 | #define ME6000_AO_06_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
67 | #define ME6000_AO_06_SINGLE_REG 0x7C // _/W | ||
68 | |||
69 | #define ME6000_AO_07_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
70 | #define ME6000_AO_07_SINGLE_REG 0x80 // _/W | ||
71 | |||
72 | #define ME6000_AO_08_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
73 | #define ME6000_AO_08_SINGLE_REG 0x84 // _/W | ||
74 | |||
75 | #define ME6000_AO_09_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
76 | #define ME6000_AO_09_SINGLE_REG 0x88 // _/W | ||
77 | |||
78 | #define ME6000_AO_10_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
79 | #define ME6000_AO_10_SINGLE_REG 0x8C // _/W | ||
80 | |||
81 | #define ME6000_AO_11_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
82 | #define ME6000_AO_11_SINGLE_REG 0x90 // _/W | ||
83 | |||
84 | #define ME6000_AO_12_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
85 | #define ME6000_AO_12_SINGLE_REG 0x94 // _/W | ||
86 | |||
87 | #define ME6000_AO_13_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
88 | #define ME6000_AO_13_SINGLE_REG 0x98 // _/W | ||
89 | |||
90 | #define ME6000_AO_14_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
91 | #define ME6000_AO_14_SINGLE_REG 0x9C // _/W | ||
92 | |||
93 | #define ME6000_AO_15_STATUS_REG ME6000_AO_SINGLE_STATUS_REG | ||
94 | #define ME6000_AO_15_SINGLE_REG 0xA0 // _/W | ||
95 | |||
96 | //ME6000_AO_CTRL_REG | ||
97 | #define ME6000_AO_MODE_SINGLE 0x00 | ||
98 | #define ME6000_AO_MODE_WRAPAROUND 0x01 | ||
99 | #define ME6000_AO_MODE_CONTINUOUS 0x02 | ||
100 | #define ME6000_AO_CTRL_MODE_MASK (ME6000_AO_MODE_WRAPAROUND | ME6000_AO_MODE_CONTINUOUS) | ||
101 | |||
102 | #define ME6000_AO_CTRL_BIT_MODE_WRAPAROUND 0x001 | ||
103 | #define ME6000_AO_CTRL_BIT_MODE_CONTINUOUS 0x002 | ||
104 | #define ME6000_AO_CTRL_BIT_STOP 0x004 | ||
105 | #define ME6000_AO_CTRL_BIT_ENABLE_FIFO 0x008 | ||
106 | #define ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG 0x010 | ||
107 | #define ME6000_AO_CTRL_BIT_EX_TRIG_EDGE 0x020 | ||
108 | #define ME6000_AO_CTRL_BIT_ENABLE_IRQ 0x040 | ||
109 | #define ME6000_AO_CTRL_BIT_IMMEDIATE_STOP 0x080 | ||
110 | #define ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH 0x800 | ||
111 | |||
112 | //ME6000_AO_STATUS_REG | ||
113 | #define ME6000_AO_STATUS_BIT_FSM 0x01 | ||
114 | #define ME6000_AO_STATUS_BIT_FF 0x02 | ||
115 | #define ME6000_AO_STATUS_BIT_HF 0x04 | ||
116 | #define ME6000_AO_STATUS_BIT_EF 0x08 | ||
117 | |||
118 | #define ME6000_AO_PRELOAD_REG 0xA8 // R/W ///ME6000_AO_SYNC_REG <==> ME6000_AO_PRELOAD_REG | ||
119 | /* | ||
120 | #define ME6000_AO_SYNC_HOLD_0 0x00000001 | ||
121 | #define ME6000_AO_SYNC_HOLD_1 0x00000002 | ||
122 | #define ME6000_AO_SYNC_HOLD_2 0x00000004 | ||
123 | #define ME6000_AO_SYNC_HOLD_3 0x00000008 | ||
124 | #define ME6000_AO_SYNC_HOLD_4 0x00000010 | ||
125 | #define ME6000_AO_SYNC_HOLD_5 0x00000020 | ||
126 | #define ME6000_AO_SYNC_HOLD_6 0x00000040 | ||
127 | #define ME6000_AO_SYNC_HOLD_7 0x00000080 | ||
128 | #define ME6000_AO_SYNC_HOLD_8 0x00000100 | ||
129 | #define ME6000_AO_SYNC_HOLD_9 0x00000200 | ||
130 | #define ME6000_AO_SYNC_HOLD_10 0x00000400 | ||
131 | #define ME6000_AO_SYNC_HOLD_11 0x00000800 | ||
132 | #define ME6000_AO_SYNC_HOLD_12 0x00001000 | ||
133 | #define ME6000_AO_SYNC_HOLD_13 0x00002000 | ||
134 | #define ME6000_AO_SYNC_HOLD_14 0x00004000 | ||
135 | #define ME6000_AO_SYNC_HOLD_15 0x00008000 | ||
136 | */ | ||
137 | #define ME6000_AO_SYNC_HOLD 0x00000001 | ||
138 | /* | ||
139 | #define ME6000_AO_SYNC_EXT_TRIG_0 0x00010000 | ||
140 | #define ME6000_AO_SYNC_EXT_TRIG_1 0x00020000 | ||
141 | #define ME6000_AO_SYNC_EXT_TRIG_2 0x00040000 | ||
142 | #define ME6000_AO_SYNC_EXT_TRIG_3 0x00080000 | ||
143 | #define ME6000_AO_SYNC_EXT_TRIG_4 0x00100000 | ||
144 | #define ME6000_AO_SYNC_EXT_TRIG_5 0x00200000 | ||
145 | #define ME6000_AO_SYNC_EXT_TRIG_6 0x00400000 | ||
146 | #define ME6000_AO_SYNC_EXT_TRIG_7 0x00800000 | ||
147 | #define ME6000_AO_SYNC_EXT_TRIG_8 0x01000000 | ||
148 | #define ME6000_AO_SYNC_EXT_TRIG_9 0x02000000 | ||
149 | #define ME6000_AO_SYNC_EXT_TRIG_10 0x04000000 | ||
150 | #define ME6000_AO_SYNC_EXT_TRIG_11 0x08000000 | ||
151 | #define ME6000_AO_SYNC_EXT_TRIG_12 0x10000000 | ||
152 | #define ME6000_AO_SYNC_EXT_TRIG_13 0x20000000 | ||
153 | #define ME6000_AO_SYNC_EXT_TRIG_14 0x40000000 | ||
154 | #define ME6000_AO_SYNC_EXT_TRIG_15 0x80000000 | ||
155 | */ | ||
156 | #define ME6000_AO_SYNC_EXT_TRIG 0x00010000 | ||
157 | |||
158 | #define ME6000_AO_EXT_TRIG 0x80000000 | ||
159 | |||
160 | // AO-IRQ | ||
161 | #define ME6000_AO_IRQ_STATUS_REG 0x60 // R/_ | ||
162 | #define ME6000_AO_00_IRQ_RESET_REG 0x64 // R/_ | ||
163 | #define ME6000_AO_01_IRQ_RESET_REG 0x68 // R/_ | ||
164 | #define ME6000_AO_02_IRQ_RESET_REG 0x6C // R/_ | ||
165 | #define ME6000_AO_03_IRQ_RESET_REG 0x70 // R/_ | ||
166 | |||
167 | #define ME6000_IRQ_STATUS_BIT_0 0x01 | ||
168 | #define ME6000_IRQ_STATUS_BIT_1 0x02 | ||
169 | #define ME6000_IRQ_STATUS_BIT_2 0x04 | ||
170 | #define ME6000_IRQ_STATUS_BIT_3 0x08 | ||
171 | |||
172 | #define ME6000_IRQ_STATUS_BIT_AO_HF ME6000_IRQ_STATUS_BIT_0 | ||
173 | |||
174 | //DUMY register | ||
175 | #define ME6000_AO_DUMY 0xFC | ||
176 | #endif | ||
177 | #endif | ||
diff --git a/drivers/staging/meilhaus/me6000_device.c b/drivers/staging/meilhaus/me6000_device.c deleted file mode 100644 index 1a6cf7f43251..000000000000 --- a/drivers/staging/meilhaus/me6000_device.c +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_device.c | ||
3 | * | ||
4 | * @brief Device class template implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include "meids.h" | ||
42 | #include "meerror.h" | ||
43 | #include "mecommon.h" | ||
44 | #include "meinternal.h" | ||
45 | |||
46 | #include "mefirmware.h" | ||
47 | |||
48 | #include "mesubdevice.h" | ||
49 | #include "medebug.h" | ||
50 | #include "medevice.h" | ||
51 | #include "me6000_reg.h" | ||
52 | #include "me6000_device.h" | ||
53 | #include "meplx_reg.h" | ||
54 | #include "me6000_dio.h" | ||
55 | #include "me6000_ao.h" | ||
56 | |||
57 | /** | ||
58 | * @brief Global variable. | ||
59 | * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts). | ||
60 | */ | ||
61 | static struct workqueue_struct *me6000_workqueue; | ||
62 | |||
63 | me_device_t *me6000_pci_constructor(struct pci_dev *pci_device) | ||
64 | { | ||
65 | me6000_device_t *me6000_device; | ||
66 | me_subdevice_t *subdevice; | ||
67 | unsigned int version_idx; | ||
68 | int err; | ||
69 | int i; | ||
70 | int high_range = 0; | ||
71 | int fifo; | ||
72 | |||
73 | PDEBUG("executed.\n"); | ||
74 | |||
75 | // Allocate structure for device instance. | ||
76 | me6000_device = kmalloc(sizeof(me6000_device_t), GFP_KERNEL); | ||
77 | |||
78 | if (!me6000_device) { | ||
79 | PERROR("Cannot get memory for device instance.\n"); | ||
80 | return NULL; | ||
81 | } | ||
82 | |||
83 | memset(me6000_device, 0, sizeof(me6000_device_t)); | ||
84 | |||
85 | // Initialize base class structure. | ||
86 | err = me_device_pci_init((me_device_t *) me6000_device, pci_device); | ||
87 | |||
88 | if (err) { | ||
89 | kfree(me6000_device); | ||
90 | PERROR("Cannot initialize device base class.\n"); | ||
91 | return NULL; | ||
92 | } | ||
93 | |||
94 | /* Download the xilinx firmware */ | ||
95 | err = me_xilinx_download(me6000_device->base.info.pci.reg_bases[1], | ||
96 | me6000_device->base.info.pci.reg_bases[2], | ||
97 | &pci_device->dev, "me6000.bin"); | ||
98 | |||
99 | if (err) { | ||
100 | me_device_deinit((me_device_t *) me6000_device); | ||
101 | kfree(me6000_device); | ||
102 | PERROR("Can't download firmware.\n"); | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
106 | /* Get the index in the device version information table. */ | ||
107 | version_idx = | ||
108 | me6000_versions_get_device_index(me6000_device->base.info.pci. | ||
109 | device_id); | ||
110 | |||
111 | // Initialize spin lock . | ||
112 | spin_lock_init(&me6000_device->preload_reg_lock); | ||
113 | spin_lock_init(&me6000_device->dio_ctrl_reg_lock); | ||
114 | |||
115 | /* Create digital input/output instances. */ | ||
116 | for (i = 0; i < me6000_versions[version_idx].dio_subdevices; i++) { | ||
117 | subdevice = | ||
118 | (me_subdevice_t *) me6000_dio_constructor(me6000_device-> | ||
119 | base.info.pci. | ||
120 | reg_bases[3], i, | ||
121 | &me6000_device-> | ||
122 | dio_ctrl_reg_lock); | ||
123 | |||
124 | if (!subdevice) { | ||
125 | me_device_deinit((me_device_t *) me6000_device); | ||
126 | kfree(me6000_device); | ||
127 | PERROR("Cannot get memory for subdevice.\n"); | ||
128 | return NULL; | ||
129 | } | ||
130 | |||
131 | me_slist_add_subdevice_tail(&me6000_device->base.slist, | ||
132 | subdevice); | ||
133 | } | ||
134 | |||
135 | /* Create analog output instances. */ | ||
136 | for (i = 0; i < me6000_versions[version_idx].ao_subdevices; i++) { | ||
137 | high_range = ((i == 8) | ||
138 | && | ||
139 | ((me6000_device->base.info.pci.device_id == | ||
140 | PCI_DEVICE_ID_MEILHAUS_ME6359) | ||
141 | || (me6000_device->base.info.pci.device_id == | ||
142 | PCI_DEVICE_ID_MEILHAUS_ME6259) | ||
143 | ) | ||
144 | )? 1 : 0; | ||
145 | |||
146 | fifo = | ||
147 | (i < | ||
148 | me6000_versions[version_idx]. | ||
149 | ao_fifo) ? ME6000_AO_HAS_FIFO : 0x0; | ||
150 | fifo |= (i < 4) ? ME6000_AO_EXTRA_HARDWARE : 0x0; | ||
151 | |||
152 | subdevice = | ||
153 | (me_subdevice_t *) me6000_ao_constructor(me6000_device-> | ||
154 | base.info.pci. | ||
155 | reg_bases[2], | ||
156 | &me6000_device-> | ||
157 | preload_reg_lock, | ||
158 | &me6000_device-> | ||
159 | preload_flags, | ||
160 | &me6000_device-> | ||
161 | triggering_flags, | ||
162 | i, fifo, | ||
163 | me6000_device-> | ||
164 | base.irq, | ||
165 | high_range, | ||
166 | me6000_workqueue); | ||
167 | |||
168 | if (!subdevice) { | ||
169 | me_device_deinit((me_device_t *) me6000_device); | ||
170 | kfree(me6000_device); | ||
171 | PERROR("Cannot get memory for subdevice.\n"); | ||
172 | return NULL; | ||
173 | } | ||
174 | |||
175 | me_slist_add_subdevice_tail(&me6000_device->base.slist, | ||
176 | subdevice); | ||
177 | } | ||
178 | |||
179 | return (me_device_t *) me6000_device; | ||
180 | } | ||
181 | EXPORT_SYMBOL(me6000_pci_constructor); | ||
182 | |||
183 | // Init and exit of module. | ||
184 | |||
185 | static int __init me6000_init(void) | ||
186 | { | ||
187 | PDEBUG("executed.\n"); | ||
188 | |||
189 | me6000_workqueue = create_singlethread_workqueue("me6000"); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static void __exit me6000_exit(void) | ||
194 | { | ||
195 | PDEBUG("executed.\n"); | ||
196 | |||
197 | flush_workqueue(me6000_workqueue); | ||
198 | destroy_workqueue(me6000_workqueue); | ||
199 | } | ||
200 | |||
201 | module_init(me6000_init); | ||
202 | module_exit(me6000_exit); | ||
203 | |||
204 | // Administrative stuff for modinfo. | ||
205 | MODULE_AUTHOR | ||
206 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
207 | MODULE_DESCRIPTION("Device Driver Module for ME-6000 Device"); | ||
208 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-6000 Devices"); | ||
209 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me6000_device.h b/drivers/staging/meilhaus/me6000_device.h deleted file mode 100644 index eed401152101..000000000000 --- a/drivers/staging/meilhaus/me6000_device.h +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_device.h | ||
3 | * | ||
4 | * @brief ME-6000 device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME6000_DEVICE_H | ||
28 | #define _ME6000_DEVICE_H | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | /** | ||
38 | * @brief Structure holding ME-6000 device capabilities. | ||
39 | */ | ||
40 | typedef struct me6000_version { | ||
41 | uint16_t device_id; | ||
42 | unsigned int dio_subdevices; | ||
43 | unsigned int ao_subdevices; | ||
44 | unsigned int ao_fifo; //How many devices have FIFO | ||
45 | } me6000_version_t; | ||
46 | |||
47 | /** | ||
48 | * @brief ME-6000 device capabilities. | ||
49 | */ | ||
50 | static me6000_version_t me6000_versions[] = { | ||
51 | {PCI_DEVICE_ID_MEILHAUS_ME6004, 0, 4, 0}, | ||
52 | {PCI_DEVICE_ID_MEILHAUS_ME6008, 0, 8, 0}, | ||
53 | {PCI_DEVICE_ID_MEILHAUS_ME600F, 0, 16, 0}, | ||
54 | |||
55 | {PCI_DEVICE_ID_MEILHAUS_ME6014, 0, 4, 0}, | ||
56 | {PCI_DEVICE_ID_MEILHAUS_ME6018, 0, 8, 0}, | ||
57 | {PCI_DEVICE_ID_MEILHAUS_ME601F, 0, 16, 0}, | ||
58 | |||
59 | {PCI_DEVICE_ID_MEILHAUS_ME6034, 0, 4, 0}, | ||
60 | {PCI_DEVICE_ID_MEILHAUS_ME6038, 0, 8, 0}, | ||
61 | {PCI_DEVICE_ID_MEILHAUS_ME603F, 0, 16, 0}, | ||
62 | |||
63 | {PCI_DEVICE_ID_MEILHAUS_ME6104, 0, 4, 4}, | ||
64 | {PCI_DEVICE_ID_MEILHAUS_ME6108, 0, 8, 4}, | ||
65 | {PCI_DEVICE_ID_MEILHAUS_ME610F, 0, 16, 4}, | ||
66 | |||
67 | {PCI_DEVICE_ID_MEILHAUS_ME6114, 0, 4, 4}, | ||
68 | {PCI_DEVICE_ID_MEILHAUS_ME6118, 0, 8, 4}, | ||
69 | {PCI_DEVICE_ID_MEILHAUS_ME611F, 0, 16, 4}, | ||
70 | |||
71 | {PCI_DEVICE_ID_MEILHAUS_ME6134, 0, 4, 4}, | ||
72 | {PCI_DEVICE_ID_MEILHAUS_ME6138, 0, 8, 4}, | ||
73 | {PCI_DEVICE_ID_MEILHAUS_ME613F, 0, 16, 4}, | ||
74 | |||
75 | {PCI_DEVICE_ID_MEILHAUS_ME6044, 2, 4, 0}, | ||
76 | {PCI_DEVICE_ID_MEILHAUS_ME6048, 2, 8, 0}, | ||
77 | {PCI_DEVICE_ID_MEILHAUS_ME604F, 2, 16, 0}, | ||
78 | |||
79 | {PCI_DEVICE_ID_MEILHAUS_ME6054, 2, 4, 0}, | ||
80 | {PCI_DEVICE_ID_MEILHAUS_ME6058, 2, 8, 0}, | ||
81 | {PCI_DEVICE_ID_MEILHAUS_ME605F, 2, 16, 0}, | ||
82 | |||
83 | {PCI_DEVICE_ID_MEILHAUS_ME6074, 2, 4, 0}, | ||
84 | {PCI_DEVICE_ID_MEILHAUS_ME6078, 2, 8, 0}, | ||
85 | {PCI_DEVICE_ID_MEILHAUS_ME607F, 2, 16, 0}, | ||
86 | |||
87 | {PCI_DEVICE_ID_MEILHAUS_ME6144, 2, 4, 4}, | ||
88 | {PCI_DEVICE_ID_MEILHAUS_ME6148, 2, 8, 4}, | ||
89 | {PCI_DEVICE_ID_MEILHAUS_ME614F, 2, 16, 4}, | ||
90 | |||
91 | {PCI_DEVICE_ID_MEILHAUS_ME6154, 2, 4, 4}, | ||
92 | {PCI_DEVICE_ID_MEILHAUS_ME6158, 2, 8, 4}, | ||
93 | {PCI_DEVICE_ID_MEILHAUS_ME615F, 2, 16, 4}, | ||
94 | |||
95 | {PCI_DEVICE_ID_MEILHAUS_ME6174, 2, 4, 4}, | ||
96 | {PCI_DEVICE_ID_MEILHAUS_ME6178, 2, 8, 4}, | ||
97 | {PCI_DEVICE_ID_MEILHAUS_ME617F, 2, 16, 4}, | ||
98 | |||
99 | {PCI_DEVICE_ID_MEILHAUS_ME6259, 2, 9, 0}, | ||
100 | |||
101 | {PCI_DEVICE_ID_MEILHAUS_ME6359, 2, 9, 4}, | ||
102 | |||
103 | {0}, | ||
104 | }; | ||
105 | |||
106 | #define ME6000_DEVICE_VERSIONS (ARRAY_SIZE(me6000_versions) - 1) /**< Returns the number of entries in #me6000_versions. */ | ||
107 | |||
108 | /** | ||
109 | * @brief Returns the index of the device entry in #me6000_versions. | ||
110 | * | ||
111 | * @param device_id The PCI device id of the device to query. | ||
112 | * @return The index of the device in #me6000_versions. | ||
113 | */ | ||
114 | static inline unsigned int me6000_versions_get_device_index(uint16_t device_id) | ||
115 | { | ||
116 | unsigned int i; | ||
117 | for (i = 0; i < ME6000_DEVICE_VERSIONS; i++) | ||
118 | if (me6000_versions[i].device_id == device_id) | ||
119 | break; | ||
120 | return i; | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * @brief The ME-6000 device class structure. | ||
125 | */ | ||
126 | typedef struct me6000_device { | ||
127 | me_device_t base; /**< The Meilhaus device base class. */ | ||
128 | |||
129 | /* Child class attributes. */ | ||
130 | spinlock_t preload_reg_lock; /**< Guards the preload register. */ | ||
131 | uint32_t preload_flags; | ||
132 | uint32_t triggering_flags; | ||
133 | |||
134 | spinlock_t dio_ctrl_reg_lock; | ||
135 | } me6000_device_t; | ||
136 | |||
137 | /** | ||
138 | * @brief The ME-6000 device class constructor. | ||
139 | * | ||
140 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
141 | * | ||
142 | * @return On succes a new ME-6000 device instance. \n | ||
143 | * NULL on error. | ||
144 | */ | ||
145 | me_device_t *me6000_pci_constructor(struct pci_dev *pci_device) | ||
146 | __attribute__ ((weak)); | ||
147 | |||
148 | #endif | ||
149 | #endif | ||
diff --git a/drivers/staging/meilhaus/me6000_dio.c b/drivers/staging/meilhaus/me6000_dio.c deleted file mode 100644 index c90686efc380..000000000000 --- a/drivers/staging/meilhaus/me6000_dio.c +++ /dev/null | |||
@@ -1,415 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_dio.c | ||
3 | * | ||
4 | * @brief ME-6000 digital input/output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me6000_dio_reg.h" | ||
48 | #include "me6000_dio.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me6000_dio_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | me6000_dio_subdevice_t *instance; | ||
62 | uint8_t mode; | ||
63 | |||
64 | PDEBUG("executed.\n"); | ||
65 | |||
66 | instance = (me6000_dio_subdevice_t *) subdevice; | ||
67 | |||
68 | if (flags) { | ||
69 | PERROR("Invalid flag specified.\n"); | ||
70 | return ME_ERRNO_INVALID_FLAGS; | ||
71 | } | ||
72 | |||
73 | ME_SUBDEVICE_ENTER; | ||
74 | |||
75 | spin_lock(&instance->subdevice_lock); | ||
76 | spin_lock(instance->ctrl_reg_lock); | ||
77 | mode = inb(instance->ctrl_reg); | ||
78 | mode &= ~(0x3 << (instance->dio_idx * 2)); | ||
79 | outb(mode, instance->ctrl_reg); | ||
80 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
81 | instance->ctrl_reg - instance->reg_base, mode); | ||
82 | spin_unlock(instance->ctrl_reg_lock); | ||
83 | |||
84 | outb(0x00, instance->port_reg); | ||
85 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
86 | instance->ctrl_reg - instance->reg_base, 0x00); | ||
87 | spin_unlock(&instance->subdevice_lock); | ||
88 | |||
89 | ME_SUBDEVICE_EXIT; | ||
90 | |||
91 | return ME_ERRNO_SUCCESS; | ||
92 | } | ||
93 | |||
94 | static int me6000_dio_io_single_config(me_subdevice_t *subdevice, | ||
95 | struct file *filep, | ||
96 | int channel, | ||
97 | int single_config, | ||
98 | int ref, | ||
99 | int trig_chan, | ||
100 | int trig_type, int trig_edge, int flags) | ||
101 | { | ||
102 | me6000_dio_subdevice_t *instance; | ||
103 | int err = ME_ERRNO_SUCCESS; | ||
104 | uint8_t mode; | ||
105 | int size = | ||
106 | flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE | ||
107 | | ME_IO_SINGLE_CONFIG_DIO_WORD | | ||
108 | ME_IO_SINGLE_CONFIG_DIO_DWORD); | ||
109 | |||
110 | PDEBUG("executed.\n"); | ||
111 | |||
112 | instance = (me6000_dio_subdevice_t *) subdevice; | ||
113 | |||
114 | ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); | ||
115 | spin_lock(instance->ctrl_reg_lock); | ||
116 | mode = inb(instance->ctrl_reg); | ||
117 | switch (size) { | ||
118 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
119 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
120 | if (channel == 0) { | ||
121 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
122 | mode &= | ||
123 | ~((ME6000_DIO_CTRL_BIT_MODE_0 | | ||
124 | ME6000_DIO_CTRL_BIT_MODE_1) << | ||
125 | (instance->dio_idx * 2)); | ||
126 | } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
127 | mode &= | ||
128 | ~((ME6000_DIO_CTRL_BIT_MODE_0 | | ||
129 | ME6000_DIO_CTRL_BIT_MODE_1) << | ||
130 | (instance->dio_idx * 2)); | ||
131 | mode |= | ||
132 | ME6000_DIO_CTRL_BIT_MODE_0 << (instance-> | ||
133 | dio_idx * 2); | ||
134 | } else { | ||
135 | PERROR | ||
136 | ("Invalid port configuration specified.\n"); | ||
137 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
138 | } | ||
139 | } else { | ||
140 | PERROR("Invalid channel number.\n"); | ||
141 | err = ME_ERRNO_INVALID_CHANNEL; | ||
142 | } | ||
143 | break; | ||
144 | |||
145 | default: | ||
146 | PERROR("Invalid flags.\n"); | ||
147 | err = ME_ERRNO_INVALID_FLAGS; | ||
148 | } | ||
149 | |||
150 | if (!err) { | ||
151 | outb(mode, instance->ctrl_reg); | ||
152 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
153 | instance->reg_base, | ||
154 | instance->ctrl_reg - instance->reg_base, mode); | ||
155 | } | ||
156 | spin_unlock(instance->ctrl_reg_lock); | ||
157 | spin_unlock(&instance->subdevice_lock); | ||
158 | |||
159 | ME_SUBDEVICE_EXIT; | ||
160 | |||
161 | return err; | ||
162 | } | ||
163 | |||
164 | static int me6000_dio_io_single_read(me_subdevice_t *subdevice, | ||
165 | struct file *filep, | ||
166 | int channel, | ||
167 | int *value, int time_out, int flags) | ||
168 | { | ||
169 | me6000_dio_subdevice_t *instance; | ||
170 | int err = ME_ERRNO_SUCCESS; | ||
171 | uint8_t mode; | ||
172 | |||
173 | PDEBUG("executed.\n"); | ||
174 | |||
175 | instance = (me6000_dio_subdevice_t *) subdevice; | ||
176 | |||
177 | ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); | ||
178 | spin_lock(instance->ctrl_reg_lock); | ||
179 | switch (flags) { | ||
180 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
181 | if ((channel >= 0) && (channel < 8)) { | ||
182 | mode = | ||
183 | inb(instance-> | ||
184 | ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | | ||
185 | ME6000_DIO_CTRL_BIT_MODE_1) << | ||
186 | (instance->dio_idx * 2)); | ||
187 | if ((mode == | ||
188 | (ME6000_DIO_CTRL_BIT_MODE_0 << | ||
189 | (instance->dio_idx * 2))) || !mode) { | ||
190 | *value = | ||
191 | inb(instance->port_reg) & (0x1 << channel); | ||
192 | } else { | ||
193 | PERROR("Port not in output or input mode.\n"); | ||
194 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
195 | } | ||
196 | } else { | ||
197 | PERROR("Invalid bit number specified.\n"); | ||
198 | err = ME_ERRNO_INVALID_CHANNEL; | ||
199 | } | ||
200 | break; | ||
201 | |||
202 | case ME_IO_SINGLE_NO_FLAGS: | ||
203 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
204 | if (channel == 0) { | ||
205 | mode = | ||
206 | inb(instance-> | ||
207 | ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | | ||
208 | ME6000_DIO_CTRL_BIT_MODE_1) << | ||
209 | (instance->dio_idx * 2)); | ||
210 | if ((mode == | ||
211 | (ME6000_DIO_CTRL_BIT_MODE_0 << | ||
212 | (instance->dio_idx * 2))) || !mode) { | ||
213 | *value = inb(instance->port_reg) & 0x00FF; | ||
214 | } else { | ||
215 | PERROR("Port not in output or input mode.\n"); | ||
216 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
217 | } | ||
218 | } else { | ||
219 | PERROR("Invalid byte number specified.\n"); | ||
220 | err = ME_ERRNO_INVALID_CHANNEL; | ||
221 | } | ||
222 | break; | ||
223 | |||
224 | default: | ||
225 | PERROR("Invalid flags specified.\n"); | ||
226 | err = ME_ERRNO_INVALID_FLAGS; | ||
227 | } | ||
228 | spin_unlock(instance->ctrl_reg_lock); | ||
229 | spin_unlock(&instance->subdevice_lock); | ||
230 | |||
231 | ME_SUBDEVICE_EXIT; | ||
232 | |||
233 | return err; | ||
234 | } | ||
235 | |||
236 | static int me6000_dio_io_single_write(me_subdevice_t *subdevice, | ||
237 | struct file *filep, | ||
238 | int channel, | ||
239 | int value, int time_out, int flags) | ||
240 | { | ||
241 | me6000_dio_subdevice_t *instance; | ||
242 | int err = ME_ERRNO_SUCCESS; | ||
243 | uint8_t mode; | ||
244 | uint8_t byte; | ||
245 | |||
246 | PDEBUG("executed.\n"); | ||
247 | |||
248 | instance = (me6000_dio_subdevice_t *) subdevice; | ||
249 | |||
250 | ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); | ||
251 | spin_lock(instance->ctrl_reg_lock); | ||
252 | switch (flags) { | ||
253 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
254 | if ((channel >= 0) && (channel < 8)) { | ||
255 | mode = | ||
256 | inb(instance-> | ||
257 | ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | | ||
258 | ME6000_DIO_CTRL_BIT_MODE_1) << | ||
259 | (instance->dio_idx * 2)); | ||
260 | |||
261 | if (mode == | ||
262 | (ME6000_DIO_CTRL_BIT_MODE_0 << | ||
263 | (instance->dio_idx * 2))) { | ||
264 | byte = inb(instance->port_reg) & 0x00FF; | ||
265 | |||
266 | if (value) | ||
267 | byte |= 0x1 << channel; | ||
268 | else | ||
269 | byte &= ~(0x1 << channel); | ||
270 | |||
271 | outb(byte, instance->port_reg); | ||
272 | } else { | ||
273 | PERROR("Port not in output or input mode.\n"); | ||
274 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
275 | } | ||
276 | } else { | ||
277 | PERROR("Invalid bit number specified.\n"); | ||
278 | err = ME_ERRNO_INVALID_CHANNEL; | ||
279 | } | ||
280 | break; | ||
281 | |||
282 | case ME_IO_SINGLE_NO_FLAGS: | ||
283 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
284 | if (channel == 0) { | ||
285 | mode = | ||
286 | inb(instance-> | ||
287 | ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | | ||
288 | ME6000_DIO_CTRL_BIT_MODE_1) << | ||
289 | (instance->dio_idx * 2)); | ||
290 | |||
291 | if (mode == | ||
292 | (ME6000_DIO_CTRL_BIT_MODE_0 << | ||
293 | (instance->dio_idx * 2))) { | ||
294 | outb(value, instance->port_reg); | ||
295 | } else { | ||
296 | PERROR("Port not in output or input mode.\n"); | ||
297 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
298 | } | ||
299 | } else { | ||
300 | PERROR("Invalid byte number specified.\n"); | ||
301 | err = ME_ERRNO_INVALID_CHANNEL; | ||
302 | } | ||
303 | break; | ||
304 | |||
305 | default: | ||
306 | PERROR("Invalid flags specified.\n"); | ||
307 | err = ME_ERRNO_INVALID_FLAGS; | ||
308 | } | ||
309 | spin_unlock(instance->ctrl_reg_lock); | ||
310 | spin_unlock(&instance->subdevice_lock); | ||
311 | |||
312 | ME_SUBDEVICE_EXIT; | ||
313 | |||
314 | return err; | ||
315 | } | ||
316 | |||
317 | static int me6000_dio_query_number_channels(me_subdevice_t *subdevice, | ||
318 | int *number) | ||
319 | { | ||
320 | PDEBUG("executed.\n"); | ||
321 | *number = 8; | ||
322 | return ME_ERRNO_SUCCESS; | ||
323 | } | ||
324 | |||
325 | static int me6000_dio_query_subdevice_type(me_subdevice_t *subdevice, | ||
326 | int *type, int *subtype) | ||
327 | { | ||
328 | PDEBUG("executed.\n"); | ||
329 | *type = ME_TYPE_DIO; | ||
330 | *subtype = ME_SUBTYPE_SINGLE; | ||
331 | return ME_ERRNO_SUCCESS; | ||
332 | } | ||
333 | |||
334 | static int me6000_dio_query_subdevice_caps(me_subdevice_t *subdevice, | ||
335 | int *caps) | ||
336 | { | ||
337 | PDEBUG("executed.\n"); | ||
338 | *caps = ME_CAPS_DIO_DIR_BYTE; | ||
339 | return ME_ERRNO_SUCCESS; | ||
340 | } | ||
341 | |||
342 | me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base, | ||
343 | unsigned int dio_idx, | ||
344 | spinlock_t *ctrl_reg_lock) | ||
345 | { | ||
346 | me6000_dio_subdevice_t *subdevice; | ||
347 | int err; | ||
348 | |||
349 | PDEBUG("executed.\n"); | ||
350 | |||
351 | /* Allocate memory for subdevice instance */ | ||
352 | subdevice = kmalloc(sizeof(me6000_dio_subdevice_t), GFP_KERNEL); | ||
353 | |||
354 | if (!subdevice) { | ||
355 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
356 | return NULL; | ||
357 | } | ||
358 | |||
359 | memset(subdevice, 0, sizeof(me6000_dio_subdevice_t)); | ||
360 | |||
361 | /* Initialize subdevice base class */ | ||
362 | err = me_subdevice_init(&subdevice->base); | ||
363 | if (err) { | ||
364 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
365 | kfree(subdevice); | ||
366 | return NULL; | ||
367 | } | ||
368 | |||
369 | /* Set the subdevice ports */ | ||
370 | subdevice->ctrl_reg = reg_base + ME6000_DIO_CTRL_REG; | ||
371 | switch (dio_idx) { | ||
372 | case 0: | ||
373 | subdevice->port_reg = reg_base + ME6000_DIO_PORT_0_REG; | ||
374 | break; | ||
375 | case 1: | ||
376 | subdevice->port_reg = reg_base + ME6000_DIO_PORT_1_REG; | ||
377 | break; | ||
378 | default: | ||
379 | err = ME_ERRNO_INVALID_SUBDEVICE; | ||
380 | } | ||
381 | |||
382 | if (err) { | ||
383 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
384 | kfree(subdevice); | ||
385 | return NULL; | ||
386 | } | ||
387 | // Initialize spin locks. | ||
388 | spin_lock_init(&subdevice->subdevice_lock); | ||
389 | |||
390 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
391 | |||
392 | /* Save digital i/o index */ | ||
393 | subdevice->dio_idx = dio_idx; | ||
394 | |||
395 | #ifdef MEDEBUG_DEBUG_REG | ||
396 | subdevice->reg_base = reg_base; | ||
397 | #endif | ||
398 | |||
399 | /* Overload base class methods. */ | ||
400 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
401 | me6000_dio_io_reset_subdevice; | ||
402 | subdevice->base.me_subdevice_io_single_config = | ||
403 | me6000_dio_io_single_config; | ||
404 | subdevice->base.me_subdevice_io_single_read = me6000_dio_io_single_read; | ||
405 | subdevice->base.me_subdevice_io_single_write = | ||
406 | me6000_dio_io_single_write; | ||
407 | subdevice->base.me_subdevice_query_number_channels = | ||
408 | me6000_dio_query_number_channels; | ||
409 | subdevice->base.me_subdevice_query_subdevice_type = | ||
410 | me6000_dio_query_subdevice_type; | ||
411 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
412 | me6000_dio_query_subdevice_caps; | ||
413 | |||
414 | return subdevice; | ||
415 | } | ||
diff --git a/drivers/staging/meilhaus/me6000_dio.h b/drivers/staging/meilhaus/me6000_dio.h deleted file mode 100644 index 858bec1c4596..000000000000 --- a/drivers/staging/meilhaus/me6000_dio.h +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_dio.h | ||
3 | * | ||
4 | * @brief ME-6000 digital input/output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME6000_DIO_H_ | ||
28 | #define _ME6000_DIO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me6000_dio_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | unsigned int dio_idx; /**< The index of the digital i/o on the device. */ | ||
45 | |||
46 | unsigned long port_reg; /**< Register holding the port status. */ | ||
47 | unsigned long ctrl_reg; /**< Register to configure the port direction. */ | ||
48 | #ifdef MEDEBUG_DEBUG_REG | ||
49 | unsigned long reg_base; | ||
50 | #endif | ||
51 | } me6000_dio_subdevice_t; | ||
52 | |||
53 | /** | ||
54 | * @brief The constructor to generate a ME-6000 digital input/ouput subdevice instance. | ||
55 | * | ||
56 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
57 | * @param dio_idx The index of the digital i/o port on the device. | ||
58 | * @param ctrl_reg_lock Spin lock protecting the control register. | ||
59 | * | ||
60 | * @return Pointer to new instance on success.\n | ||
61 | * NULL on error. | ||
62 | */ | ||
63 | me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base, | ||
64 | unsigned int dio_idx, | ||
65 | spinlock_t * ctrl_reg_lock); | ||
66 | |||
67 | #endif | ||
68 | #endif | ||
diff --git a/drivers/staging/meilhaus/me6000_dio_reg.h b/drivers/staging/meilhaus/me6000_dio_reg.h deleted file mode 100644 index e67a791a1e69..000000000000 --- a/drivers/staging/meilhaus/me6000_dio_reg.h +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_dio_reg.h | ||
3 | * | ||
4 | * @brief ME-6000 digital input/output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME6000_DIO_REG_H_ | ||
28 | #define _ME6000_DIO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME6000_DIO_CTRL_REG 0x00 // R/W | ||
33 | #define ME6000_DIO_PORT_0_REG 0x01 // R/W | ||
34 | #define ME6000_DIO_PORT_1_REG 0x02 // R/W | ||
35 | #define ME6000_DIO_PORT_REG ME6000_DIO_PORT_0_REG // R/W | ||
36 | |||
37 | #define ME6000_DIO_CTRL_BIT_MODE_0 0x01 | ||
38 | #define ME6000_DIO_CTRL_BIT_MODE_1 0x02 | ||
39 | #define ME6000_DIO_CTRL_BIT_MODE_2 0x04 | ||
40 | #define ME6000_DIO_CTRL_BIT_MODE_3 0x08 | ||
41 | |||
42 | #endif | ||
43 | #endif | ||
diff --git a/drivers/staging/meilhaus/me6000_reg.h b/drivers/staging/meilhaus/me6000_reg.h deleted file mode 100644 index d35273003415..000000000000 --- a/drivers/staging/meilhaus/me6000_reg.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /** | ||
2 | * @file me6000_reg.h | ||
3 | * | ||
4 | * @brief ME-6000 device register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME6000_REG_H_ | ||
28 | #define _ME6000_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME6000_INIT_XILINX_REG 0xAC // R/- | ||
33 | |||
34 | #endif | ||
35 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8100_device.c b/drivers/staging/meilhaus/me8100_device.c deleted file mode 100644 index 41a9345cee5d..000000000000 --- a/drivers/staging/meilhaus/me8100_device.c +++ /dev/null | |||
@@ -1,185 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_device.c | ||
3 | * | ||
4 | * @brief ME-8100 device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef __KERNEL__ | ||
28 | # define __KERNEL__ | ||
29 | #endif | ||
30 | |||
31 | #ifndef MODULE | ||
32 | # define MODULE | ||
33 | #endif | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/pci.h> | ||
38 | #include <linux/slab.h> | ||
39 | |||
40 | #include "meids.h" | ||
41 | #include "meerror.h" | ||
42 | #include "mecommon.h" | ||
43 | #include "meinternal.h" | ||
44 | |||
45 | #include "medebug.h" | ||
46 | #include "medevice.h" | ||
47 | #include "me8100_device.h" | ||
48 | #include "mesubdevice.h" | ||
49 | #include "me8100_di.h" | ||
50 | #include "me8100_do.h" | ||
51 | #include "me8254.h" | ||
52 | |||
53 | me_device_t *me8100_pci_constructor(struct pci_dev *pci_device) | ||
54 | { | ||
55 | me8100_device_t *me8100_device; | ||
56 | me_subdevice_t *subdevice; | ||
57 | unsigned int version_idx; | ||
58 | int err; | ||
59 | int i; | ||
60 | |||
61 | PDEBUG("executed.\n"); | ||
62 | |||
63 | // Allocate structure for device instance. | ||
64 | me8100_device = kmalloc(sizeof(me8100_device_t), GFP_KERNEL); | ||
65 | |||
66 | if (!me8100_device) { | ||
67 | PERROR("Cannot get memory for device instance.\n"); | ||
68 | return NULL; | ||
69 | } | ||
70 | |||
71 | memset(me8100_device, 0, sizeof(me8100_device_t)); | ||
72 | |||
73 | // Initialize base class structure. | ||
74 | err = me_device_pci_init((me_device_t *) me8100_device, pci_device); | ||
75 | |||
76 | if (err) { | ||
77 | kfree(me8100_device); | ||
78 | PERROR("Cannot initialize device base class.\n"); | ||
79 | return NULL; | ||
80 | } | ||
81 | |||
82 | /* Get the index in the device version information table. */ | ||
83 | version_idx = | ||
84 | me8100_versions_get_device_index(me8100_device->base.info.pci. | ||
85 | device_id); | ||
86 | |||
87 | // Initialize spin lock . | ||
88 | spin_lock_init(&me8100_device->dio_ctrl_reg_lock); | ||
89 | spin_lock_init(&me8100_device->ctr_ctrl_reg_lock); | ||
90 | spin_lock_init(&me8100_device->clk_src_reg_lock); | ||
91 | |||
92 | // Create subdevice instances. | ||
93 | |||
94 | for (i = 0; i < me8100_versions[version_idx].di_subdevices; i++) { | ||
95 | subdevice = | ||
96 | (me_subdevice_t *) me8100_di_constructor(me8100_device-> | ||
97 | base.info.pci. | ||
98 | reg_bases[2], | ||
99 | me8100_device-> | ||
100 | base.info.pci. | ||
101 | reg_bases[1], i, | ||
102 | me8100_device-> | ||
103 | base.irq, | ||
104 | &me8100_device-> | ||
105 | dio_ctrl_reg_lock); | ||
106 | |||
107 | if (!subdevice) { | ||
108 | me_device_deinit((me_device_t *) me8100_device); | ||
109 | kfree(me8100_device); | ||
110 | PERROR("Cannot get memory for subdevice.\n"); | ||
111 | return NULL; | ||
112 | } | ||
113 | |||
114 | me_slist_add_subdevice_tail(&me8100_device->base.slist, | ||
115 | subdevice); | ||
116 | } | ||
117 | |||
118 | for (i = 0; i < me8100_versions[version_idx].do_subdevices; i++) { | ||
119 | subdevice = | ||
120 | (me_subdevice_t *) me8100_do_constructor(me8100_device-> | ||
121 | base.info.pci. | ||
122 | reg_bases[2], i, | ||
123 | &me8100_device-> | ||
124 | dio_ctrl_reg_lock); | ||
125 | |||
126 | if (!subdevice) { | ||
127 | me_device_deinit((me_device_t *) me8100_device); | ||
128 | kfree(me8100_device); | ||
129 | PERROR("Cannot get memory for subdevice.\n"); | ||
130 | return NULL; | ||
131 | } | ||
132 | |||
133 | me_slist_add_subdevice_tail(&me8100_device->base.slist, | ||
134 | subdevice); | ||
135 | } | ||
136 | |||
137 | for (i = 0; i < me8100_versions[version_idx].ctr_subdevices; i++) { | ||
138 | subdevice = | ||
139 | (me_subdevice_t *) me8254_constructor(me8100_device->base. | ||
140 | info.pci.device_id, | ||
141 | me8100_device->base. | ||
142 | info.pci.reg_bases[2], | ||
143 | 0, i, | ||
144 | &me8100_device-> | ||
145 | ctr_ctrl_reg_lock, | ||
146 | &me8100_device-> | ||
147 | clk_src_reg_lock); | ||
148 | |||
149 | if (!subdevice) { | ||
150 | me_device_deinit((me_device_t *) me8100_device); | ||
151 | kfree(me8100_device); | ||
152 | PERROR("Cannot get memory for subdevice.\n"); | ||
153 | return NULL; | ||
154 | } | ||
155 | |||
156 | me_slist_add_subdevice_tail(&me8100_device->base.slist, | ||
157 | subdevice); | ||
158 | } | ||
159 | |||
160 | return (me_device_t *) me8100_device; | ||
161 | } | ||
162 | EXPORT_SYMBOL(me8100_pci_constructor); | ||
163 | |||
164 | // Init and exit of module. | ||
165 | |||
166 | static int __init me8100_init(void) | ||
167 | { | ||
168 | PDEBUG("executed.\n."); | ||
169 | return ME_ERRNO_SUCCESS; | ||
170 | } | ||
171 | |||
172 | static void __exit me8100_exit(void) | ||
173 | { | ||
174 | PDEBUG("executed.\n."); | ||
175 | } | ||
176 | |||
177 | module_init(me8100_init); | ||
178 | |||
179 | module_exit(me8100_exit); | ||
180 | |||
181 | // Administrative stuff for modinfo. | ||
182 | MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>"); | ||
183 | MODULE_DESCRIPTION("Device Driver Module for Template Device"); | ||
184 | MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); | ||
185 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me8100_device.h b/drivers/staging/meilhaus/me8100_device.h deleted file mode 100644 index 238dc0622801..000000000000 --- a/drivers/staging/meilhaus/me8100_device.h +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_device.h | ||
3 | * | ||
4 | * @brief ME-8100 device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8100_DEVICE_H | ||
28 | #define _ME8100_DEVICE_H | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | /** | ||
38 | * @brief Structure holding ME-8100 device capabilities. | ||
39 | */ | ||
40 | typedef struct me8100_version { | ||
41 | uint16_t device_id; | ||
42 | unsigned int di_subdevices; | ||
43 | unsigned int do_subdevices; | ||
44 | unsigned int ctr_subdevices; | ||
45 | } me8100_version_t; | ||
46 | |||
47 | /** | ||
48 | * @brief Device capabilities. | ||
49 | */ | ||
50 | static me8100_version_t me8100_versions[] = { | ||
51 | {PCI_DEVICE_ID_MEILHAUS_ME8100_A, 1, 1, 3}, | ||
52 | {PCI_DEVICE_ID_MEILHAUS_ME8100_B, 2, 2, 3}, | ||
53 | {0}, | ||
54 | }; | ||
55 | |||
56 | #define ME8100_DEVICE_VERSIONS (ARRAY_SIZE(me8100_versions) - 1) /**< Returns the number of entries in #me8100_versions. */ | ||
57 | |||
58 | /** | ||
59 | * @brief Returns the index of the device entry in #me8100_versions. | ||
60 | * | ||
61 | * @param device_id The PCI device id of the device to query. | ||
62 | * @return The index of the device in #me8100_versions. | ||
63 | */ | ||
64 | static inline unsigned int me8100_versions_get_device_index(uint16_t device_id) | ||
65 | { | ||
66 | unsigned int i; | ||
67 | for (i = 0; i < ME8100_DEVICE_VERSIONS; i++) | ||
68 | if (me8100_versions[i].device_id == device_id) | ||
69 | break; | ||
70 | return i; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * @brief The ME-8100 device class structure. | ||
75 | */ | ||
76 | typedef struct me8100_device { | ||
77 | me_device_t base; /**< The Meilhaus device base class. */ | ||
78 | |||
79 | /* Child class attributes. */ | ||
80 | spinlock_t dio_ctrl_reg_lock; | ||
81 | spinlock_t ctr_ctrl_reg_lock; | ||
82 | spinlock_t clk_src_reg_lock; | ||
83 | } me8100_device_t; | ||
84 | |||
85 | /** | ||
86 | * @brief The ME-8100 device class constructor. | ||
87 | * | ||
88 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
89 | * | ||
90 | * @return On succes a new ME-8100 device instance. \n | ||
91 | * NULL on error. | ||
92 | */ | ||
93 | me_device_t *me8100_pci_constructor(struct pci_dev *pci_device) | ||
94 | __attribute__ ((weak)); | ||
95 | |||
96 | #endif | ||
97 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8100_di.c b/drivers/staging/meilhaus/me8100_di.c deleted file mode 100644 index 1a3f2692d7ab..000000000000 --- a/drivers/staging/meilhaus/me8100_di.c +++ /dev/null | |||
@@ -1,684 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_di.c | ||
3 | * | ||
4 | * @brief ME-8100 digital input subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | |||
43 | #include "medefines.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "meids.h" | ||
47 | #include "medebug.h" | ||
48 | #include "meplx_reg.h" | ||
49 | #include "me8100_reg.h" | ||
50 | #include "me8100_di_reg.h" | ||
51 | #include "me8100_di.h" | ||
52 | |||
53 | /* | ||
54 | * Defines | ||
55 | */ | ||
56 | |||
57 | /* | ||
58 | * Functions | ||
59 | */ | ||
60 | |||
61 | static int me8100_di_io_reset_subdevice(struct me_subdevice *subdevice, | ||
62 | struct file *filep, int flags) | ||
63 | { | ||
64 | me8100_di_subdevice_t *instance; | ||
65 | unsigned short ctrl; | ||
66 | unsigned long cpu_flags; | ||
67 | |||
68 | PDEBUG("executed.\n"); | ||
69 | |||
70 | instance = (me8100_di_subdevice_t *) subdevice; | ||
71 | |||
72 | if (flags) { | ||
73 | PERROR("Invalid flag specified.\n"); | ||
74 | return ME_ERRNO_INVALID_FLAGS; | ||
75 | } | ||
76 | |||
77 | ME_SUBDEVICE_ENTER; | ||
78 | |||
79 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
80 | spin_lock(instance->ctrl_reg_lock); | ||
81 | ctrl = inw(instance->ctrl_reg); | ||
82 | ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0); | ||
83 | outw(ctrl, instance->ctrl_reg); | ||
84 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
85 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
86 | spin_unlock(instance->ctrl_reg_lock); | ||
87 | |||
88 | outw(0, instance->mask_reg); | ||
89 | PDEBUG_REG("mask_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
90 | instance->mask_reg - instance->reg_base, 0); | ||
91 | outw(0, instance->pattern_reg); | ||
92 | PDEBUG_REG("pattern_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
93 | instance->pattern_reg - instance->reg_base, 0); | ||
94 | instance->rised = -1; | ||
95 | instance->irq_count = 0; | ||
96 | instance->filtering_flag = 0; | ||
97 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
98 | |||
99 | outl(PLX_INTCSR_LOCAL_INT1_EN | | ||
100 | PLX_INTCSR_LOCAL_INT1_POL | | ||
101 | PLX_INTCSR_LOCAL_INT2_EN | | ||
102 | PLX_INTCSR_LOCAL_INT2_POL | | ||
103 | PLX_INTCSR_PCI_INT_EN, instance->irq_status_reg); | ||
104 | PDEBUG_REG("plx:irq_status_reg outl(0x%lX)=0x%x\n", | ||
105 | instance->irq_status_reg, | ||
106 | PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL | | ||
107 | PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL | | ||
108 | PLX_INTCSR_PCI_INT_EN); | ||
109 | |||
110 | wake_up_interruptible_all(&instance->wait_queue); | ||
111 | ME_SUBDEVICE_EXIT; | ||
112 | |||
113 | return ME_ERRNO_SUCCESS; | ||
114 | } | ||
115 | |||
116 | static int me8100_di_io_irq_start(me_subdevice_t *subdevice, | ||
117 | struct file *filep, | ||
118 | int channel, | ||
119 | int irq_source, | ||
120 | int irq_edge, int irq_arg, int flags) | ||
121 | { | ||
122 | me8100_di_subdevice_t *instance; | ||
123 | int err = ME_ERRNO_SUCCESS; | ||
124 | uint16_t ctrl; | ||
125 | unsigned long cpu_flags; | ||
126 | |||
127 | PDEBUG("executed.\n"); | ||
128 | |||
129 | instance = (me8100_di_subdevice_t *) subdevice; | ||
130 | |||
131 | if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { | ||
132 | if (flags & | ||
133 | ~(ME_IO_IRQ_START_PATTERN_FILTERING | | ||
134 | ME_IO_IRQ_START_DIO_WORD)) { | ||
135 | PERROR("Invalid flag specified.\n"); | ||
136 | return ME_ERRNO_INVALID_FLAGS; | ||
137 | } | ||
138 | |||
139 | if (irq_edge != ME_IRQ_EDGE_NOT_USED) { | ||
140 | PERROR("Invalid irq edge specified.\n"); | ||
141 | return ME_ERRNO_INVALID_IRQ_EDGE; | ||
142 | } | ||
143 | } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { | ||
144 | if (flags & | ||
145 | ~(ME_IO_IRQ_START_EXTENDED_STATUS | | ||
146 | ME_IO_IRQ_START_DIO_WORD)) { | ||
147 | PERROR("Invalid flag specified.\n"); | ||
148 | return ME_ERRNO_INVALID_FLAGS; | ||
149 | } | ||
150 | |||
151 | if (irq_edge != ME_IRQ_EDGE_ANY) { | ||
152 | PERROR("Invalid irq edge specified.\n"); | ||
153 | return ME_ERRNO_INVALID_IRQ_EDGE; | ||
154 | } | ||
155 | |||
156 | if (!(irq_arg & 0xFFFF)) { | ||
157 | PERROR("No mask specified.\n"); | ||
158 | return ME_ERRNO_INVALID_IRQ_ARG; | ||
159 | } | ||
160 | } else { | ||
161 | PERROR("Invalid irq source specified.\n"); | ||
162 | return ME_ERRNO_INVALID_IRQ_SOURCE; | ||
163 | } | ||
164 | |||
165 | if (channel) { | ||
166 | PERROR("Invalid channel specified.\n"); | ||
167 | return ME_ERRNO_INVALID_CHANNEL; | ||
168 | } | ||
169 | |||
170 | ME_SUBDEVICE_ENTER; | ||
171 | |||
172 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
173 | if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { | ||
174 | outw(irq_arg, instance->pattern_reg); | ||
175 | instance->compare_value = irq_arg; | ||
176 | instance->filtering_flag = | ||
177 | (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0; | ||
178 | } | ||
179 | if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { | ||
180 | outw(irq_arg, instance->mask_reg); | ||
181 | } | ||
182 | |||
183 | spin_lock(instance->ctrl_reg_lock); | ||
184 | ctrl = inw(instance->ctrl_reg); | ||
185 | ctrl |= ME8100_DIO_CTRL_BIT_INTB_0; | ||
186 | if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { | ||
187 | ctrl &= ~ME8100_DIO_CTRL_BIT_INTB_1; | ||
188 | } | ||
189 | |||
190 | if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { | ||
191 | ctrl |= ME8100_DIO_CTRL_BIT_INTB_1; | ||
192 | } | ||
193 | outw(ctrl, instance->ctrl_reg); | ||
194 | PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
195 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
196 | spin_unlock(instance->ctrl_reg_lock); | ||
197 | |||
198 | instance->rised = 0; | ||
199 | instance->status_value = 0; | ||
200 | instance->status_value_edges = 0; | ||
201 | instance->line_value = inw(instance->port_reg); | ||
202 | instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS; | ||
203 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
204 | |||
205 | ME_SUBDEVICE_EXIT; | ||
206 | |||
207 | return err; | ||
208 | } | ||
209 | |||
210 | static int me8100_di_io_irq_wait(me_subdevice_t *subdevice, | ||
211 | struct file *filep, | ||
212 | int channel, | ||
213 | int *irq_count, | ||
214 | int *value, int time_out, int flags) | ||
215 | { | ||
216 | me8100_di_subdevice_t *instance; | ||
217 | int err = ME_ERRNO_SUCCESS; | ||
218 | long t = 0; | ||
219 | unsigned long cpu_flags; | ||
220 | int count; | ||
221 | |||
222 | PDEBUG("executed.\n"); | ||
223 | PDEVELOP("PID: %d.\n", current->pid); | ||
224 | |||
225 | instance = (me8100_di_subdevice_t *) subdevice; | ||
226 | |||
227 | if (flags & | ||
228 | ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) { | ||
229 | PERROR("Invalid flag specified.\n"); | ||
230 | return ME_ERRNO_INVALID_FLAGS; | ||
231 | } | ||
232 | |||
233 | if (channel) { | ||
234 | PERROR("Invalid channel specified.\n"); | ||
235 | return ME_ERRNO_INVALID_CHANNEL; | ||
236 | } | ||
237 | |||
238 | if (time_out < 0) { | ||
239 | PERROR("Invalid time_out specified.\n"); | ||
240 | return ME_ERRNO_INVALID_TIMEOUT; | ||
241 | } | ||
242 | |||
243 | if (time_out) { | ||
244 | t = (time_out * HZ) / 1000; | ||
245 | |||
246 | if (t == 0) | ||
247 | t = 1; | ||
248 | } | ||
249 | |||
250 | ME_SUBDEVICE_ENTER; | ||
251 | |||
252 | if (instance->rised <= 0) { | ||
253 | instance->rised = 0; | ||
254 | count = instance->irq_count; | ||
255 | |||
256 | if (time_out) { | ||
257 | t = wait_event_interruptible_timeout(instance-> | ||
258 | wait_queue, | ||
259 | ((count != | ||
260 | instance-> | ||
261 | irq_count) | ||
262 | || (instance-> | ||
263 | rised < 0)), | ||
264 | t); | ||
265 | // t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t); | ||
266 | if (t == 0) { | ||
267 | PERROR("Wait on interrupt timed out.\n"); | ||
268 | err = ME_ERRNO_TIMEOUT; | ||
269 | } | ||
270 | } else { | ||
271 | wait_event_interruptible(instance->wait_queue, | ||
272 | ((count != instance->irq_count) | ||
273 | || (instance->rised < 0))); | ||
274 | // wait_event_interruptible(instance->wait_queue, (instance->rised != 0)); | ||
275 | } | ||
276 | |||
277 | if (instance->rised < 0) { | ||
278 | PERROR("Wait on interrupt aborted by user.\n"); | ||
279 | err = ME_ERRNO_CANCELLED; | ||
280 | } | ||
281 | } | ||
282 | |||
283 | if (signal_pending(current)) { | ||
284 | PERROR("Wait on interrupt aborted by signal.\n"); | ||
285 | err = ME_ERRNO_SIGNAL; | ||
286 | } | ||
287 | |||
288 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
289 | *irq_count = instance->irq_count; | ||
290 | if (!err) { | ||
291 | if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) { | ||
292 | *value = instance->status_value; | ||
293 | } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) { | ||
294 | *value = instance->status_value_edges; | ||
295 | } else { // Use default | ||
296 | if (!instance->status_flag) { | ||
297 | *value = instance->status_value; | ||
298 | } else { | ||
299 | *value = instance->status_value_edges; | ||
300 | } | ||
301 | } | ||
302 | instance->rised = 0; | ||
303 | /* | ||
304 | instance->status_value = 0; | ||
305 | instance->status_value_edges = 0; | ||
306 | */ | ||
307 | } else { | ||
308 | *value = 0; | ||
309 | } | ||
310 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
311 | |||
312 | ME_SUBDEVICE_EXIT; | ||
313 | |||
314 | return err; | ||
315 | } | ||
316 | |||
317 | static int me8100_di_io_irq_stop(me_subdevice_t *subdevice, | ||
318 | struct file *filep, int channel, int flags) | ||
319 | { | ||
320 | me8100_di_subdevice_t *instance; | ||
321 | uint16_t ctrl; | ||
322 | unsigned long cpu_flags; | ||
323 | |||
324 | PDEBUG("executed.\n"); | ||
325 | |||
326 | instance = (me8100_di_subdevice_t *) subdevice; | ||
327 | |||
328 | if (flags) { | ||
329 | PERROR("Invalid flag specified.\n"); | ||
330 | return ME_ERRNO_INVALID_FLAGS; | ||
331 | } | ||
332 | |||
333 | if (channel) { | ||
334 | PERROR("Invalid channel specified.\n"); | ||
335 | return ME_ERRNO_INVALID_CHANNEL; | ||
336 | } | ||
337 | |||
338 | ME_SUBDEVICE_ENTER; | ||
339 | |||
340 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
341 | spin_lock(instance->ctrl_reg_lock); | ||
342 | ctrl = inw(instance->ctrl_reg); | ||
343 | ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0); | ||
344 | outw(ctrl, instance->ctrl_reg); | ||
345 | PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
346 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
347 | spin_unlock(instance->ctrl_reg_lock); | ||
348 | instance->rised = -1; | ||
349 | instance->status_value = 0; | ||
350 | instance->status_value_edges = 0; | ||
351 | instance->filtering_flag = 0; | ||
352 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
353 | wake_up_interruptible_all(&instance->wait_queue); | ||
354 | |||
355 | ME_SUBDEVICE_EXIT; | ||
356 | |||
357 | return ME_ERRNO_SUCCESS; | ||
358 | } | ||
359 | |||
360 | static int me8100_di_io_single_config(me_subdevice_t *subdevice, | ||
361 | struct file *filep, | ||
362 | int channel, | ||
363 | int single_config, | ||
364 | int ref, | ||
365 | int trig_chan, | ||
366 | int trig_type, int trig_edge, int flags) | ||
367 | { | ||
368 | me8100_di_subdevice_t *instance; | ||
369 | int err = ME_ERRNO_SUCCESS; | ||
370 | |||
371 | PDEBUG("executed.\n"); | ||
372 | |||
373 | instance = (me8100_di_subdevice_t *) subdevice; | ||
374 | |||
375 | ME_SUBDEVICE_ENTER; | ||
376 | |||
377 | spin_lock(&instance->subdevice_lock); | ||
378 | |||
379 | switch (flags) { | ||
380 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
381 | case ME_IO_SINGLE_CONFIG_DIO_WORD: | ||
382 | if (channel == 0) { | ||
383 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
384 | } else { | ||
385 | PERROR | ||
386 | ("Invalid port configuration specified.\n"); | ||
387 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
388 | } | ||
389 | } else { | ||
390 | PERROR("Invalid channel number.\n"); | ||
391 | err = ME_ERRNO_INVALID_CHANNEL; | ||
392 | } | ||
393 | break; | ||
394 | |||
395 | default: | ||
396 | PERROR("Invalid flags specified.\n"); | ||
397 | err = ME_ERRNO_INVALID_FLAGS; | ||
398 | } | ||
399 | |||
400 | spin_unlock(&instance->subdevice_lock); | ||
401 | |||
402 | ME_SUBDEVICE_EXIT; | ||
403 | |||
404 | return err; | ||
405 | } | ||
406 | |||
407 | static int me8100_di_io_single_read(me_subdevice_t *subdevice, | ||
408 | struct file *filep, | ||
409 | int channel, | ||
410 | int *value, int time_out, int flags) | ||
411 | { | ||
412 | me8100_di_subdevice_t *instance; | ||
413 | int err = ME_ERRNO_SUCCESS; | ||
414 | |||
415 | PDEBUG("executed.\n"); | ||
416 | |||
417 | instance = (me8100_di_subdevice_t *) subdevice; | ||
418 | |||
419 | ME_SUBDEVICE_ENTER; | ||
420 | |||
421 | spin_lock(&instance->subdevice_lock); | ||
422 | |||
423 | switch (flags) { | ||
424 | |||
425 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
426 | if ((channel >= 0) && (channel < 16)) { | ||
427 | *value = inw(instance->port_reg) & (0x1 << channel); | ||
428 | } else { | ||
429 | PERROR("Invalid bit number specified.\n"); | ||
430 | err = ME_ERRNO_INVALID_CHANNEL; | ||
431 | } | ||
432 | break; | ||
433 | |||
434 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
435 | if (channel == 0) { | ||
436 | *value = inw(instance->port_reg) & 0xFF; | ||
437 | } else if (channel == 1) { | ||
438 | *value = (inw(instance->port_reg) >> 8) & 0xFF; | ||
439 | } else { | ||
440 | PERROR("Invalid byte number specified.\n"); | ||
441 | err = ME_ERRNO_INVALID_CHANNEL; | ||
442 | } | ||
443 | break; | ||
444 | |||
445 | case ME_IO_SINGLE_NO_FLAGS: | ||
446 | case ME_IO_SINGLE_TYPE_DIO_WORD: | ||
447 | if (channel == 0) { | ||
448 | *value = inw(instance->port_reg); | ||
449 | } else { | ||
450 | PERROR("Invalid word number specified.\n"); | ||
451 | err = ME_ERRNO_INVALID_CHANNEL; | ||
452 | } | ||
453 | |||
454 | break; | ||
455 | |||
456 | default: | ||
457 | PERROR("Invalid flags specified.\n"); | ||
458 | err = ME_ERRNO_INVALID_FLAGS; | ||
459 | } | ||
460 | |||
461 | spin_unlock(&instance->subdevice_lock); | ||
462 | |||
463 | ME_SUBDEVICE_EXIT; | ||
464 | |||
465 | return err; | ||
466 | } | ||
467 | |||
468 | static int me8100_di_query_number_channels(me_subdevice_t *subdevice, | ||
469 | int *number) | ||
470 | { | ||
471 | PDEBUG("executed.\n"); | ||
472 | *number = 16; | ||
473 | return ME_ERRNO_SUCCESS; | ||
474 | } | ||
475 | |||
476 | static int me8100_di_query_subdevice_type(me_subdevice_t *subdevice, | ||
477 | int *type, int *subtype) | ||
478 | { | ||
479 | PDEBUG("executed.\n"); | ||
480 | *type = ME_TYPE_DI; | ||
481 | *subtype = ME_SUBTYPE_SINGLE; | ||
482 | return ME_ERRNO_SUCCESS; | ||
483 | } | ||
484 | |||
485 | static int me8100_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
486 | { | ||
487 | PDEBUG("executed.\n"); | ||
488 | *caps = ME_CAPS_DIO_BIT_PATTERN_IRQ | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY; | ||
489 | return ME_ERRNO_SUCCESS; | ||
490 | } | ||
491 | |||
492 | static void me8100_di_destructor(struct me_subdevice *subdevice) | ||
493 | { | ||
494 | me8100_di_subdevice_t *instance; | ||
495 | |||
496 | PDEBUG("executed.\n"); | ||
497 | |||
498 | instance = (me8100_di_subdevice_t *) subdevice; | ||
499 | |||
500 | free_irq(instance->irq, (void *)instance); | ||
501 | me_subdevice_deinit(&instance->base); | ||
502 | kfree(instance); | ||
503 | } | ||
504 | |||
505 | static irqreturn_t me8100_isr(int irq, void *dev_id) | ||
506 | { | ||
507 | me8100_di_subdevice_t *instance; | ||
508 | uint32_t icsr; | ||
509 | |||
510 | uint16_t irq_status; | ||
511 | uint16_t line_value = 0; | ||
512 | |||
513 | uint32_t status_val = 0; | ||
514 | |||
515 | PDEBUG("executed.\n"); | ||
516 | |||
517 | instance = (me8100_di_subdevice_t *) dev_id; | ||
518 | |||
519 | if (irq != instance->irq) { | ||
520 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
521 | return IRQ_NONE; | ||
522 | } | ||
523 | |||
524 | icsr = inl(instance->irq_status_reg); | ||
525 | if (instance->di_idx == 0) { | ||
526 | |||
527 | if ((icsr & | ||
528 | (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN | | ||
529 | PLX_INTCSR_LOCAL_INT1_EN)) != | ||
530 | (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN | | ||
531 | PLX_INTCSR_LOCAL_INT1_EN)) { | ||
532 | PINFO | ||
533 | ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n", | ||
534 | jiffies, __func__, icsr); | ||
535 | return IRQ_NONE; | ||
536 | } | ||
537 | } else if (instance->di_idx == 1) { | ||
538 | if ((icsr & | ||
539 | (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN | | ||
540 | PLX_INTCSR_LOCAL_INT2_EN)) != | ||
541 | (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN | | ||
542 | PLX_INTCSR_LOCAL_INT2_EN)) { | ||
543 | PINFO | ||
544 | ("%ld Shared interrupt. %s(): idx=1 plx:irq_status_reg=0x%04X\n", | ||
545 | jiffies, __func__, icsr); | ||
546 | return IRQ_NONE; | ||
547 | } | ||
548 | } else { | ||
549 | PERROR("%s():Wrong interrupt idx=%d csr=0x%X.\n", __func__, | ||
550 | instance->di_idx, icsr); | ||
551 | return IRQ_NONE; | ||
552 | } | ||
553 | |||
554 | PDEBUG("me8100_isr():Interrupt from idx=%d occured.\n", | ||
555 | instance->di_idx); | ||
556 | spin_lock(&instance->subdevice_lock); | ||
557 | inw(instance->irq_reset_reg); | ||
558 | line_value = inw(instance->port_reg); | ||
559 | |||
560 | irq_status = instance->line_value ^ line_value; | ||
561 | |||
562 | // Make extended information. | ||
563 | status_val |= (0x00FF & (~(uint16_t) instance->line_value & line_value)) << 16; //Raise | ||
564 | status_val |= (0x00FF & ((uint16_t) instance->line_value & ~line_value)); //Fall | ||
565 | |||
566 | instance->line_value = line_value; | ||
567 | |||
568 | if (instance->rised == 0) { | ||
569 | instance->status_value = irq_status; | ||
570 | instance->status_value_edges = status_val; | ||
571 | } else { | ||
572 | instance->status_value |= irq_status; | ||
573 | instance->status_value_edges |= status_val; | ||
574 | } | ||
575 | |||
576 | if (instance->filtering_flag) { // For compare mode only. | ||
577 | if (instance->compare_value == instance->line_value) { | ||
578 | instance->rised = 1; | ||
579 | instance->irq_count++; | ||
580 | } | ||
581 | } else { | ||
582 | instance->rised = 1; | ||
583 | instance->irq_count++; | ||
584 | } | ||
585 | |||
586 | spin_unlock(&instance->subdevice_lock); | ||
587 | wake_up_interruptible_all(&instance->wait_queue); | ||
588 | |||
589 | return IRQ_HANDLED; | ||
590 | } | ||
591 | |||
592 | me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base, | ||
593 | uint32_t plx_reg_base, | ||
594 | unsigned int di_idx, | ||
595 | int irq, | ||
596 | spinlock_t *ctrl_reg_lock) | ||
597 | { | ||
598 | me8100_di_subdevice_t *subdevice; | ||
599 | int err; | ||
600 | |||
601 | PDEBUG("executed.\n"); | ||
602 | |||
603 | /* Allocate memory for subdevice instance */ | ||
604 | subdevice = kmalloc(sizeof(me8100_di_subdevice_t), GFP_KERNEL); | ||
605 | |||
606 | if (!subdevice) { | ||
607 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
608 | return NULL; | ||
609 | } | ||
610 | |||
611 | memset(subdevice, 0, sizeof(me8100_di_subdevice_t)); | ||
612 | |||
613 | /* Initialize subdevice base class */ | ||
614 | err = me_subdevice_init(&subdevice->base); | ||
615 | |||
616 | if (err) { | ||
617 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
618 | kfree(subdevice); | ||
619 | return NULL; | ||
620 | } | ||
621 | // Initialize spin locks. | ||
622 | spin_lock_init(&subdevice->subdevice_lock); | ||
623 | |||
624 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
625 | |||
626 | /* Save the subdevice index. */ | ||
627 | subdevice->di_idx = di_idx; | ||
628 | |||
629 | /* Initialize wait queue */ | ||
630 | init_waitqueue_head(&subdevice->wait_queue); | ||
631 | |||
632 | /* Register interrupt service routine. */ | ||
633 | subdevice->irq = irq; | ||
634 | err = request_irq(subdevice->irq, me8100_isr, | ||
635 | IRQF_DISABLED | IRQF_SHARED, | ||
636 | ME8100_NAME, (void *)subdevice); | ||
637 | |||
638 | if (err) { | ||
639 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
640 | kfree(subdevice); | ||
641 | return NULL; | ||
642 | } | ||
643 | PINFO("Registered irq=%d.\n", subdevice->irq); | ||
644 | |||
645 | /* Initialize the registers */ | ||
646 | subdevice->ctrl_reg = | ||
647 | me8100_reg_base + ME8100_CTRL_REG_A + di_idx * ME8100_REG_OFFSET; | ||
648 | subdevice->port_reg = | ||
649 | me8100_reg_base + ME8100_DI_REG_A + di_idx * ME8100_REG_OFFSET; | ||
650 | subdevice->mask_reg = | ||
651 | me8100_reg_base + ME8100_MASK_REG_A + di_idx * ME8100_REG_OFFSET; | ||
652 | subdevice->pattern_reg = | ||
653 | me8100_reg_base + ME8100_PATTERN_REG_A + di_idx * ME8100_REG_OFFSET; | ||
654 | subdevice->din_int_reg = | ||
655 | me8100_reg_base + ME8100_INT_DI_REG_A + di_idx * ME8100_REG_OFFSET; | ||
656 | subdevice->irq_reset_reg = | ||
657 | me8100_reg_base + ME8100_RES_INT_REG_A + di_idx * ME8100_REG_OFFSET; | ||
658 | subdevice->irq_status_reg = plx_reg_base + PLX_INTCSR; | ||
659 | #ifdef MEDEBUG_DEBUG_REG | ||
660 | subdevice->reg_base = me8100_reg_base; | ||
661 | #endif | ||
662 | |||
663 | /* Overload base class methods. */ | ||
664 | subdevice->base.me_subdevice_io_irq_start = me8100_di_io_irq_start; | ||
665 | subdevice->base.me_subdevice_io_irq_wait = me8100_di_io_irq_wait; | ||
666 | subdevice->base.me_subdevice_io_irq_stop = me8100_di_io_irq_stop; | ||
667 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
668 | me8100_di_io_reset_subdevice; | ||
669 | subdevice->base.me_subdevice_io_single_config = | ||
670 | me8100_di_io_single_config; | ||
671 | subdevice->base.me_subdevice_io_single_read = me8100_di_io_single_read; | ||
672 | subdevice->base.me_subdevice_query_number_channels = | ||
673 | me8100_di_query_number_channels; | ||
674 | subdevice->base.me_subdevice_query_subdevice_type = | ||
675 | me8100_di_query_subdevice_type; | ||
676 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
677 | me8100_di_query_subdevice_caps; | ||
678 | subdevice->base.me_subdevice_destructor = me8100_di_destructor; | ||
679 | |||
680 | subdevice->rised = 0; | ||
681 | subdevice->irq_count = 0; | ||
682 | |||
683 | return subdevice; | ||
684 | } | ||
diff --git a/drivers/staging/meilhaus/me8100_di.h b/drivers/staging/meilhaus/me8100_di.h deleted file mode 100644 index e1db79129175..000000000000 --- a/drivers/staging/meilhaus/me8100_di.h +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_di.h | ||
3 | * | ||
4 | * @brief ME-8100 digital input subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8100_DI_H_ | ||
28 | #define _ME8100_DI_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me8100_di_subdevice { | ||
38 | // Inheritance | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; | ||
44 | |||
45 | unsigned di_idx; | ||
46 | |||
47 | int irq; | ||
48 | volatile int rised; | ||
49 | unsigned int irq_count; | ||
50 | |||
51 | uint status_flag; /**< Default interupt status flag */ | ||
52 | uint status_value; /**< Interupt status */ | ||
53 | uint status_value_edges; /**< Extended interupt status */ | ||
54 | uint line_value; | ||
55 | |||
56 | uint16_t compare_value; | ||
57 | uint8_t filtering_flag; | ||
58 | |||
59 | wait_queue_head_t wait_queue; | ||
60 | |||
61 | unsigned long ctrl_reg; | ||
62 | unsigned long port_reg; | ||
63 | unsigned long mask_reg; | ||
64 | unsigned long pattern_reg; | ||
65 | unsigned long long din_int_reg; | ||
66 | unsigned long irq_reset_reg; | ||
67 | unsigned long irq_status_reg; | ||
68 | #ifdef MEDEBUG_DEBUG_REG | ||
69 | unsigned long reg_base; | ||
70 | #endif | ||
71 | |||
72 | } me8100_di_subdevice_t; | ||
73 | |||
74 | /** | ||
75 | * @brief The constructor to generate a ME-8100 digital input subdevice instance. | ||
76 | * | ||
77 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
78 | * | ||
79 | * @return Pointer to new instance on success.\n | ||
80 | * NULL on error. | ||
81 | */ | ||
82 | me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base, | ||
83 | uint32_t plx_reg_base, | ||
84 | unsigned int di_idx, | ||
85 | int irq, | ||
86 | spinlock_t * ctrl_leg_lock); | ||
87 | |||
88 | #endif | ||
89 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8100_di_reg.h b/drivers/staging/meilhaus/me8100_di_reg.h deleted file mode 100644 index 063bd193709e..000000000000 --- a/drivers/staging/meilhaus/me8100_di_reg.h +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_di_reg.h | ||
3 | * | ||
4 | * @brief ME-8100 digital input subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8100_DI_REG_H_ | ||
28 | #define _ME8100_DI_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME8100_RES_INT_REG_A 0x02 //(r, ) | ||
33 | #define ME8100_DI_REG_A 0x04 //(r, ) | ||
34 | #define ME8100_PATTERN_REG_A 0x08 //( ,w) | ||
35 | #define ME8100_MASK_REG_A 0x0A //( ,w) | ||
36 | #define ME8100_INT_DI_REG_A 0x0A //(r, ) | ||
37 | |||
38 | #define ME8100_RES_INT_REG_B 0x0E //(r, ) | ||
39 | #define ME8100_DI_REG_B 0x10 //(r, ) | ||
40 | #define ME8100_PATTERN_REG_B 0x14 //( ,w) | ||
41 | #define ME8100_MASK_REG_B 0x16 //( ,w) | ||
42 | #define ME8100_INT_DI_REG_B 0x16 //(r, ) | ||
43 | |||
44 | #define ME8100_REG_OFFSET 0x0C | ||
45 | |||
46 | #endif | ||
47 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8100_do.c b/drivers/staging/meilhaus/me8100_do.c deleted file mode 100644 index 81651a90cc05..000000000000 --- a/drivers/staging/meilhaus/me8100_do.c +++ /dev/null | |||
@@ -1,391 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_do.c | ||
3 | * | ||
4 | * @brief ME-8100 digital output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me8100_reg.h" | ||
48 | #include "me8100_do_reg.h" | ||
49 | #include "me8100_do.h" | ||
50 | |||
51 | /* | ||
52 | * Defines | ||
53 | */ | ||
54 | |||
55 | /* | ||
56 | * Functions | ||
57 | */ | ||
58 | |||
59 | static int me8100_do_io_reset_subdevice(struct me_subdevice *subdevice, | ||
60 | struct file *filep, int flags) | ||
61 | { | ||
62 | me8100_do_subdevice_t *instance; | ||
63 | uint16_t ctrl; | ||
64 | |||
65 | PDEBUG("executed.\n"); | ||
66 | |||
67 | instance = (me8100_do_subdevice_t *) subdevice; | ||
68 | |||
69 | if (flags) { | ||
70 | PERROR("Invalid flag specified.\n"); | ||
71 | return ME_ERRNO_INVALID_FLAGS; | ||
72 | } | ||
73 | |||
74 | ME_SUBDEVICE_ENTER; | ||
75 | |||
76 | spin_lock(&instance->subdevice_lock); | ||
77 | spin_lock(instance->ctrl_reg_lock); | ||
78 | ctrl = inw(instance->ctrl_reg); | ||
79 | ctrl &= ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0; | ||
80 | outw(ctrl, instance->ctrl_reg); | ||
81 | PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
82 | instance->ctrl_reg - instance->reg_base, ctrl); | ||
83 | spin_unlock(instance->ctrl_reg_lock); | ||
84 | outw(0, instance->port_reg); | ||
85 | instance->port_reg_mirror = 0; | ||
86 | PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
87 | instance->port_reg - instance->reg_base, 0); | ||
88 | spin_unlock(&instance->subdevice_lock); | ||
89 | |||
90 | ME_SUBDEVICE_EXIT; | ||
91 | |||
92 | return ME_ERRNO_SUCCESS; | ||
93 | } | ||
94 | |||
95 | static int me8100_do_io_single_config(me_subdevice_t *subdevice, | ||
96 | struct file *filep, | ||
97 | int channel, | ||
98 | int single_config, | ||
99 | int ref, | ||
100 | int trig_chan, | ||
101 | int trig_type, int trig_edge, int flags) | ||
102 | { | ||
103 | me8100_do_subdevice_t *instance; | ||
104 | int err = ME_ERRNO_SUCCESS; | ||
105 | int config; | ||
106 | |||
107 | PDEBUG("executed.\n"); | ||
108 | |||
109 | instance = (me8100_do_subdevice_t *) subdevice; | ||
110 | |||
111 | ME_SUBDEVICE_ENTER; | ||
112 | |||
113 | spin_lock(&instance->subdevice_lock); | ||
114 | spin_lock(instance->ctrl_reg_lock); | ||
115 | config = inw(instance->ctrl_reg); | ||
116 | switch (flags) { | ||
117 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
118 | case ME_IO_SINGLE_CONFIG_DIO_WORD: | ||
119 | if (channel == 0) { | ||
120 | if (single_config == | ||
121 | ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE) { | ||
122 | config &= ~(ME8100_DIO_CTRL_BIT_ENABLE_DIO); | ||
123 | } else if (single_config == ME_SINGLE_CONFIG_DIO_SINK) { | ||
124 | config |= ME8100_DIO_CTRL_BIT_ENABLE_DIO; | ||
125 | config &= ~ME8100_DIO_CTRL_BIT_SOURCE; | ||
126 | } else if (single_config == ME_SINGLE_CONFIG_DIO_SOURCE) { | ||
127 | config |= | ||
128 | ME8100_DIO_CTRL_BIT_ENABLE_DIO | | ||
129 | ME8100_DIO_CTRL_BIT_SOURCE; | ||
130 | } else { | ||
131 | PERROR | ||
132 | ("Invalid port configuration specified.\n"); | ||
133 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
134 | } | ||
135 | } else { | ||
136 | PERROR("Invalid word number specified.\n"); | ||
137 | err = ME_ERRNO_INVALID_CHANNEL; | ||
138 | } | ||
139 | break; | ||
140 | |||
141 | default: | ||
142 | PERROR("Invalid flags specified.\n"); | ||
143 | err = ME_ERRNO_INVALID_FLAGS; | ||
144 | } | ||
145 | |||
146 | if (!err) { | ||
147 | outw(config, instance->ctrl_reg); | ||
148 | PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
149 | instance->reg_base, | ||
150 | instance->ctrl_reg - instance->reg_base, config); | ||
151 | } | ||
152 | |||
153 | spin_unlock(instance->ctrl_reg_lock); | ||
154 | spin_unlock(&instance->subdevice_lock); | ||
155 | |||
156 | ME_SUBDEVICE_EXIT; | ||
157 | |||
158 | return err; | ||
159 | } | ||
160 | |||
161 | static int me8100_do_io_single_read(me_subdevice_t *subdevice, | ||
162 | struct file *filep, | ||
163 | int channel, | ||
164 | int *value, int time_out, int flags) | ||
165 | { | ||
166 | me8100_do_subdevice_t *instance; | ||
167 | int err = ME_ERRNO_SUCCESS; | ||
168 | |||
169 | PDEBUG("executed.\n"); | ||
170 | |||
171 | instance = (me8100_do_subdevice_t *) subdevice; | ||
172 | |||
173 | ME_SUBDEVICE_ENTER; | ||
174 | |||
175 | spin_lock(&instance->subdevice_lock); | ||
176 | switch (flags) { | ||
177 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
178 | if ((channel >= 0) && (channel < 16)) { | ||
179 | *value = instance->port_reg_mirror & (0x1 << channel); | ||
180 | } else { | ||
181 | PERROR("Invalid bit number specified.\n"); | ||
182 | err = ME_ERRNO_INVALID_CHANNEL; | ||
183 | } | ||
184 | break; | ||
185 | |||
186 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
187 | if (channel == 0) { | ||
188 | *value = instance->port_reg_mirror & 0xFF; | ||
189 | } else if (channel == 1) { | ||
190 | *value = (instance->port_reg_mirror >> 8) & 0xFF; | ||
191 | } else { | ||
192 | PERROR("Invalid byte number specified.\n"); | ||
193 | err = ME_ERRNO_INVALID_CHANNEL; | ||
194 | } | ||
195 | break; | ||
196 | |||
197 | case ME_IO_SINGLE_NO_FLAGS: | ||
198 | case ME_IO_SINGLE_TYPE_DIO_WORD: | ||
199 | if (channel == 0) { | ||
200 | *value = instance->port_reg_mirror; | ||
201 | } else { | ||
202 | PERROR("Invalid word number specified.\n"); | ||
203 | err = ME_ERRNO_INVALID_CHANNEL; | ||
204 | } | ||
205 | break; | ||
206 | |||
207 | default: | ||
208 | PERROR("Invalid flags specified.\n"); | ||
209 | err = ME_ERRNO_INVALID_FLAGS; | ||
210 | } | ||
211 | spin_unlock(&instance->subdevice_lock); | ||
212 | |||
213 | ME_SUBDEVICE_EXIT; | ||
214 | |||
215 | return err; | ||
216 | } | ||
217 | |||
218 | static int me8100_do_io_single_write(me_subdevice_t *subdevice, | ||
219 | struct file *filep, | ||
220 | int channel, | ||
221 | int value, int time_out, int flags) | ||
222 | { | ||
223 | me8100_do_subdevice_t *instance; | ||
224 | int err = ME_ERRNO_SUCCESS; | ||
225 | |||
226 | PDEBUG("executed.\n"); | ||
227 | |||
228 | instance = (me8100_do_subdevice_t *) subdevice; | ||
229 | |||
230 | ME_SUBDEVICE_ENTER; | ||
231 | |||
232 | spin_lock(&instance->subdevice_lock); | ||
233 | switch (flags) { | ||
234 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
235 | if ((channel >= 0) && (channel < 16)) { | ||
236 | instance->port_reg_mirror = | ||
237 | value ? (instance-> | ||
238 | port_reg_mirror | (0x1 << channel)) | ||
239 | : (instance->port_reg_mirror & ~(0x1 << channel)); | ||
240 | outw(instance->port_reg_mirror, instance->port_reg); | ||
241 | PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
242 | instance->reg_base, | ||
243 | instance->port_reg - instance->reg_base, | ||
244 | instance->port_reg_mirror); | ||
245 | } else { | ||
246 | PERROR("Invalid bit number specified.\n"); | ||
247 | err = ME_ERRNO_INVALID_CHANNEL; | ||
248 | } | ||
249 | break; | ||
250 | |||
251 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
252 | if (channel == 0) { | ||
253 | instance->port_reg_mirror &= ~0xFF; | ||
254 | instance->port_reg_mirror |= value & 0xFF; | ||
255 | outw(instance->port_reg_mirror, instance->port_reg); | ||
256 | PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
257 | instance->reg_base, | ||
258 | instance->port_reg - instance->reg_base, | ||
259 | instance->port_reg_mirror); | ||
260 | } else if (channel == 1) { | ||
261 | instance->port_reg_mirror &= ~0xFF00; | ||
262 | instance->port_reg_mirror |= (value << 8) & 0xFF00; | ||
263 | outw(instance->port_reg_mirror, instance->port_reg); | ||
264 | PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
265 | instance->reg_base, | ||
266 | instance->port_reg - instance->reg_base, | ||
267 | instance->port_reg_mirror); | ||
268 | } else { | ||
269 | PERROR("Invalid byte number specified.\n"); | ||
270 | err = ME_ERRNO_INVALID_CHANNEL; | ||
271 | } | ||
272 | break; | ||
273 | |||
274 | case ME_IO_SINGLE_NO_FLAGS: | ||
275 | case ME_IO_SINGLE_TYPE_DIO_WORD: | ||
276 | if (channel == 0) { | ||
277 | instance->port_reg_mirror = value; | ||
278 | outw(value, instance->port_reg); | ||
279 | PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", | ||
280 | instance->reg_base, | ||
281 | instance->port_reg - instance->reg_base, | ||
282 | value); | ||
283 | } else { | ||
284 | PERROR("Invalid byte number specified.\n"); | ||
285 | err = ME_ERRNO_INVALID_CHANNEL; | ||
286 | } | ||
287 | break; | ||
288 | |||
289 | default: | ||
290 | PERROR("Invalid flags specified.\n"); | ||
291 | err = ME_ERRNO_INVALID_FLAGS; | ||
292 | } | ||
293 | spin_unlock(&instance->subdevice_lock); | ||
294 | |||
295 | ME_SUBDEVICE_EXIT; | ||
296 | |||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static int me8100_do_query_number_channels(me_subdevice_t *subdevice, | ||
301 | int *number) | ||
302 | { | ||
303 | PDEBUG("executed.\n"); | ||
304 | *number = 16; | ||
305 | return ME_ERRNO_SUCCESS; | ||
306 | } | ||
307 | |||
308 | static int me8100_do_query_subdevice_type(me_subdevice_t *subdevice, | ||
309 | int *type, int *subtype) | ||
310 | { | ||
311 | PDEBUG("executed.\n"); | ||
312 | *type = ME_TYPE_DO; | ||
313 | *subtype = ME_SUBTYPE_SINGLE; | ||
314 | return ME_ERRNO_SUCCESS; | ||
315 | } | ||
316 | |||
317 | static int me8100_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
318 | { | ||
319 | PDEBUG("executed.\n"); | ||
320 | *caps = ME_CAPS_DIO_SINK_SOURCE; | ||
321 | return ME_ERRNO_SUCCESS; | ||
322 | } | ||
323 | |||
324 | me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base, | ||
325 | unsigned int do_idx, | ||
326 | spinlock_t *ctrl_reg_lock) | ||
327 | { | ||
328 | me8100_do_subdevice_t *subdevice; | ||
329 | int err; | ||
330 | |||
331 | PDEBUG("executed.\n"); | ||
332 | |||
333 | /* Allocate memory for subdevice instance */ | ||
334 | subdevice = kmalloc(sizeof(me8100_do_subdevice_t), GFP_KERNEL); | ||
335 | |||
336 | if (!subdevice) { | ||
337 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
338 | return NULL; | ||
339 | } | ||
340 | |||
341 | memset(subdevice, 0, sizeof(me8100_do_subdevice_t)); | ||
342 | |||
343 | /* Initialize subdevice base class */ | ||
344 | err = me_subdevice_init(&subdevice->base); | ||
345 | |||
346 | if (err) { | ||
347 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
348 | kfree(subdevice); | ||
349 | return NULL; | ||
350 | } | ||
351 | |||
352 | /* Initialize registers */ | ||
353 | if (do_idx == 0) { | ||
354 | subdevice->port_reg = reg_base + ME8100_DO_REG_A; | ||
355 | subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_A; | ||
356 | } else if (do_idx == 1) { | ||
357 | subdevice->port_reg = reg_base + ME8100_DO_REG_B; | ||
358 | subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_B; | ||
359 | } else { | ||
360 | PERROR("Wrong subdevice idx=%d.\n", do_idx); | ||
361 | kfree(subdevice); | ||
362 | return NULL; | ||
363 | } | ||
364 | #ifdef MEDEBUG_DEBUG_REG | ||
365 | subdevice->reg_base = reg_base; | ||
366 | #endif | ||
367 | |||
368 | // Initialize spin locks. | ||
369 | spin_lock_init(&subdevice->subdevice_lock); | ||
370 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
371 | |||
372 | /* Save the subdevice index */ | ||
373 | subdevice->do_idx = do_idx; | ||
374 | |||
375 | /* Overload base class methods. */ | ||
376 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
377 | me8100_do_io_reset_subdevice; | ||
378 | subdevice->base.me_subdevice_io_single_config = | ||
379 | me8100_do_io_single_config; | ||
380 | subdevice->base.me_subdevice_io_single_read = me8100_do_io_single_read; | ||
381 | subdevice->base.me_subdevice_io_single_write = | ||
382 | me8100_do_io_single_write; | ||
383 | subdevice->base.me_subdevice_query_number_channels = | ||
384 | me8100_do_query_number_channels; | ||
385 | subdevice->base.me_subdevice_query_subdevice_type = | ||
386 | me8100_do_query_subdevice_type; | ||
387 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
388 | me8100_do_query_subdevice_caps; | ||
389 | |||
390 | return subdevice; | ||
391 | } | ||
diff --git a/drivers/staging/meilhaus/me8100_do.h b/drivers/staging/meilhaus/me8100_do.h deleted file mode 100644 index acf880136663..000000000000 --- a/drivers/staging/meilhaus/me8100_do.h +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_do.h | ||
3 | * | ||
4 | * @brief ME-8100 digital output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8100_DO_H_ | ||
28 | #define _ME8100_DO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me8100_do_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect the #ctrl_reg. */ | ||
44 | |||
45 | unsigned int do_idx; | ||
46 | |||
47 | uint16_t port_reg_mirror; /**< Mirror used to store current port register setting which is write only. */ | ||
48 | |||
49 | unsigned long port_reg; /**< Register holding the port status. */ | ||
50 | unsigned long ctrl_reg; /**< Control register. */ | ||
51 | #ifdef MEDEBUG_DEBUG_REG | ||
52 | unsigned long reg_base; | ||
53 | #endif | ||
54 | } me8100_do_subdevice_t; | ||
55 | |||
56 | /** | ||
57 | * @brief The constructor to generate a ME-8100 digital output subdevice instance. | ||
58 | * | ||
59 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
60 | * @param do_idx The index of the digital output subdevice on this device. | ||
61 | * | ||
62 | * @return Pointer to new instance on success.\n | ||
63 | * NULL on error. | ||
64 | */ | ||
65 | me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base, | ||
66 | unsigned int do_idx, | ||
67 | spinlock_t * ctrl_reg_lock); | ||
68 | |||
69 | #endif | ||
70 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8100_do_reg.h b/drivers/staging/meilhaus/me8100_do_reg.h deleted file mode 100644 index 13a23802b31a..000000000000 --- a/drivers/staging/meilhaus/me8100_do_reg.h +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_ao_reg.h | ||
3 | * | ||
4 | * @brief ME-8100 analog output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8100_DO_REG_H_ | ||
28 | #define _ME8100_DO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME8100_DO_REG_A 0x06 //( ,w) | ||
33 | #define ME8100_DO_REG_B 0x12 //( ,w) | ||
34 | |||
35 | #endif | ||
36 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8100_reg.h b/drivers/staging/meilhaus/me8100_reg.h deleted file mode 100644 index d8c4b1c6b153..000000000000 --- a/drivers/staging/meilhaus/me8100_reg.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8100_reg.h | ||
3 | * | ||
4 | * @brief ME-8100 register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8100_REG_H_ | ||
28 | #define _ME8100_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME8100_CTRL_REG_A 0x00 //( ,w) | ||
33 | #define ME8100_CTRL_REG_B 0x0C //( ,w) | ||
34 | |||
35 | #define ME8100_DIO_CTRL_BIT_SOURCE 0x10 | ||
36 | #define ME8100_DIO_CTRL_BIT_INTB_1 0x20 | ||
37 | #define ME8100_DIO_CTRL_BIT_INTB_0 0x40 | ||
38 | #define ME8100_DIO_CTRL_BIT_ENABLE_DIO 0x80 | ||
39 | |||
40 | #endif | ||
41 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_device.c b/drivers/staging/meilhaus/me8200_device.c deleted file mode 100644 index b313679fc5c3..000000000000 --- a/drivers/staging/meilhaus/me8200_device.c +++ /dev/null | |||
@@ -1,192 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_device.c | ||
3 | * | ||
4 | * @brief ME-8200 device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/slab.h> | ||
40 | |||
41 | #include "meids.h" | ||
42 | #include "meerror.h" | ||
43 | #include "mecommon.h" | ||
44 | #include "meinternal.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "meplx_reg.h" | ||
48 | #include "medevice.h" | ||
49 | #include "me8200_device.h" | ||
50 | #include "mesubdevice.h" | ||
51 | #include "me8200_di.h" | ||
52 | #include "me8200_do.h" | ||
53 | #include "me8200_dio.h" | ||
54 | |||
55 | me_device_t *me8200_pci_constructor(struct pci_dev *pci_device) | ||
56 | { | ||
57 | me8200_device_t *me8200_device; | ||
58 | me_subdevice_t *subdevice; | ||
59 | unsigned int version_idx; | ||
60 | int err; | ||
61 | int i; | ||
62 | |||
63 | PDEBUG("executed.\n"); | ||
64 | |||
65 | // Allocate structure for device instance. | ||
66 | me8200_device = kmalloc(sizeof(me8200_device_t), GFP_KERNEL); | ||
67 | |||
68 | if (!me8200_device) { | ||
69 | PERROR("Cannot get memory for device instance.\n"); | ||
70 | return NULL; | ||
71 | } | ||
72 | |||
73 | memset(me8200_device, 0, sizeof(me8200_device_t)); | ||
74 | |||
75 | // Initialize base class structure. | ||
76 | err = me_device_pci_init((me_device_t *) me8200_device, pci_device); | ||
77 | |||
78 | if (err) { | ||
79 | kfree(me8200_device); | ||
80 | PERROR("Cannot initialize device base class.\n"); | ||
81 | return NULL; | ||
82 | } | ||
83 | |||
84 | /* Get the index in the device version information table. */ | ||
85 | version_idx = | ||
86 | me8200_versions_get_device_index(me8200_device->base.info.pci. | ||
87 | device_id); | ||
88 | |||
89 | // Initialize spin lock . | ||
90 | spin_lock_init(&me8200_device->irq_ctrl_lock); | ||
91 | spin_lock_init(&me8200_device->irq_mode_lock); | ||
92 | spin_lock_init(&me8200_device->dio_ctrl_lock); | ||
93 | |||
94 | /* Setup the PLX interrupt configuration */ | ||
95 | outl(PLX_INTCSR_LOCAL_INT1_EN | | ||
96 | PLX_INTCSR_LOCAL_INT1_POL | | ||
97 | PLX_INTCSR_LOCAL_INT2_EN | | ||
98 | PLX_INTCSR_LOCAL_INT2_POL | | ||
99 | PLX_INTCSR_PCI_INT_EN, | ||
100 | me8200_device->base.info.pci.reg_bases[1] + PLX_INTCSR); | ||
101 | |||
102 | // Create subdevice instances. | ||
103 | |||
104 | for (i = 0; i < me8200_versions[version_idx].di_subdevices; i++) { | ||
105 | subdevice = | ||
106 | (me_subdevice_t *) me8200_di_constructor(me8200_device-> | ||
107 | base.info.pci. | ||
108 | reg_bases[2], i, | ||
109 | me8200_device-> | ||
110 | base.irq, | ||
111 | &me8200_device-> | ||
112 | irq_ctrl_lock, | ||
113 | &me8200_device-> | ||
114 | irq_mode_lock); | ||
115 | |||
116 | if (!subdevice) { | ||
117 | me_device_deinit((me_device_t *) me8200_device); | ||
118 | kfree(me8200_device); | ||
119 | PERROR("Cannot get memory for subdevice.\n"); | ||
120 | return NULL; | ||
121 | } | ||
122 | |||
123 | me_slist_add_subdevice_tail(&me8200_device->base.slist, | ||
124 | subdevice); | ||
125 | } | ||
126 | |||
127 | for (i = 0; i < me8200_versions[version_idx].do_subdevices; i++) { | ||
128 | subdevice = | ||
129 | (me_subdevice_t *) me8200_do_constructor(me8200_device-> | ||
130 | base.info.pci. | ||
131 | reg_bases[2], i, | ||
132 | me8200_device-> | ||
133 | base.irq, | ||
134 | &me8200_device-> | ||
135 | irq_mode_lock); | ||
136 | |||
137 | if (!subdevice) { | ||
138 | me_device_deinit((me_device_t *) me8200_device); | ||
139 | kfree(me8200_device); | ||
140 | PERROR("Cannot get memory for subdevice.\n"); | ||
141 | return NULL; | ||
142 | } | ||
143 | |||
144 | me_slist_add_subdevice_tail(&me8200_device->base.slist, | ||
145 | subdevice); | ||
146 | } | ||
147 | |||
148 | for (i = 0; i < me8200_versions[version_idx].dio_subdevices; i++) { | ||
149 | subdevice = | ||
150 | (me_subdevice_t *) me8200_dio_constructor(me8200_device-> | ||
151 | base.info.pci. | ||
152 | reg_bases[2], i, | ||
153 | &me8200_device-> | ||
154 | dio_ctrl_lock); | ||
155 | |||
156 | if (!subdevice) { | ||
157 | me_device_deinit((me_device_t *) me8200_device); | ||
158 | kfree(me8200_device); | ||
159 | PERROR("Cannot get memory for subdevice.\n"); | ||
160 | return NULL; | ||
161 | } | ||
162 | |||
163 | me_slist_add_subdevice_tail(&me8200_device->base.slist, | ||
164 | subdevice); | ||
165 | } | ||
166 | |||
167 | return (me_device_t *) me8200_device; | ||
168 | } | ||
169 | EXPORT_SYMBOL(me8200_pci_constructor); | ||
170 | |||
171 | // Init and exit of module. | ||
172 | |||
173 | static int __init me8200_init(void) | ||
174 | { | ||
175 | PDEBUG("executed.\n."); | ||
176 | return 0; | ||
177 | } | ||
178 | |||
179 | static void __exit me8200_exit(void) | ||
180 | { | ||
181 | PDEBUG("executed.\n."); | ||
182 | } | ||
183 | |||
184 | module_init(me8200_init); | ||
185 | |||
186 | module_exit(me8200_exit); | ||
187 | |||
188 | // Administrative stuff for modinfo. | ||
189 | MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>"); | ||
190 | MODULE_DESCRIPTION("Device Driver Module for Template Device"); | ||
191 | MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); | ||
192 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/me8200_device.h b/drivers/staging/meilhaus/me8200_device.h deleted file mode 100644 index 66f50842dac0..000000000000 --- a/drivers/staging/meilhaus/me8200_device.h +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_device.h | ||
3 | * | ||
4 | * @brief ME-8200 device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_DEVICE_H | ||
28 | #define _ME8200_DEVICE_H | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | /** | ||
38 | * @brief Structure holding ME-8200 device capabilities. | ||
39 | */ | ||
40 | typedef struct me8200_version { | ||
41 | uint16_t device_id; | ||
42 | unsigned int di_subdevices; | ||
43 | unsigned int do_subdevices; | ||
44 | unsigned int dio_subdevices; | ||
45 | } me8200_version_t; | ||
46 | |||
47 | /** | ||
48 | * @brief Device capabilities. | ||
49 | */ | ||
50 | static me8200_version_t me8200_versions[] = { | ||
51 | {PCI_DEVICE_ID_MEILHAUS_ME8200_A, 1, 1, 2}, | ||
52 | {PCI_DEVICE_ID_MEILHAUS_ME8200_B, 2, 2, 2}, | ||
53 | {0}, | ||
54 | }; | ||
55 | |||
56 | #define ME8200_DEVICE_VERSIONS (ARRAY_SIZE(me8200_versions) - 1) /**< Returns the number of entries in #me8200_versions. */ | ||
57 | |||
58 | /** | ||
59 | * @brief Returns the index of the device entry in #me8200_versions. | ||
60 | * | ||
61 | * @param device_id The PCI device id of the device to query. | ||
62 | * @return The index of the device in #me8200_versions. | ||
63 | */ | ||
64 | static inline unsigned int me8200_versions_get_device_index(uint16_t device_id) | ||
65 | { | ||
66 | unsigned int i; | ||
67 | for (i = 0; i < ME8200_DEVICE_VERSIONS; i++) | ||
68 | if (me8200_versions[i].device_id == device_id) | ||
69 | break; | ||
70 | return i; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * @brief The ME-8200 device class structure. | ||
75 | */ | ||
76 | typedef struct me8200_device { | ||
77 | me_device_t base; /**< The Meilhaus device base class. */ | ||
78 | |||
79 | /* Child class attributes. */ | ||
80 | spinlock_t irq_ctrl_lock; /**< Lock for the interrupt control register. */ | ||
81 | spinlock_t irq_mode_lock; /**< Lock for the interrupt mode register. */ | ||
82 | spinlock_t dio_ctrl_lock; /**< Lock for the digital i/o control register. */ | ||
83 | } me8200_device_t; | ||
84 | |||
85 | /** | ||
86 | * @brief The ME-8200 device class constructor. | ||
87 | * | ||
88 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
89 | * | ||
90 | * @return On succes a new ME-8200 device instance. \n | ||
91 | * NULL on error. | ||
92 | */ | ||
93 | me_device_t *me8200_pci_constructor(struct pci_dev *pci_device) | ||
94 | __attribute__ ((weak)); | ||
95 | |||
96 | #endif | ||
97 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_di.c b/drivers/staging/meilhaus/me8200_di.c deleted file mode 100644 index fd1af0f0565e..000000000000 --- a/drivers/staging/meilhaus/me8200_di.c +++ /dev/null | |||
@@ -1,832 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_di.c | ||
3 | * | ||
4 | * @brief ME-8200 digital input subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | ///Includes | ||
33 | #include <linux/module.h> | ||
34 | |||
35 | #include <linux/slab.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/io.h> | ||
38 | #include <linux/types.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | |||
41 | #include "medefines.h" | ||
42 | #include "meerror.h" | ||
43 | |||
44 | #include "meids.h" | ||
45 | #include "medebug.h" | ||
46 | #include "me8200_reg.h" | ||
47 | #include "me8200_di_reg.h" | ||
48 | #include "me8200_di.h" | ||
49 | |||
50 | /// Defines | ||
51 | static void me8200_di_destructor(struct me_subdevice *subdevice); | ||
52 | static int me8200_di_io_irq_start(me_subdevice_t *subdevice, | ||
53 | struct file *filep, | ||
54 | int channel, | ||
55 | int irq_source, | ||
56 | int irq_edge, int irq_arg, int flags); | ||
57 | static int me8200_di_io_irq_wait(me_subdevice_t *subdevice, | ||
58 | struct file *filep, | ||
59 | int channel, | ||
60 | int *irq_count, | ||
61 | int *value, int time_out, int flags); | ||
62 | static int me8200_di_io_irq_stop(me_subdevice_t *subdevice, | ||
63 | struct file *filep, int channel, int flags); | ||
64 | static int me8200_di_io_single_config(me_subdevice_t *subdevice, | ||
65 | struct file *filep, | ||
66 | int channel, | ||
67 | int single_config, | ||
68 | int ref, | ||
69 | int trig_chan, | ||
70 | int trig_type, int trig_edge, int flags); | ||
71 | static int me8200_di_io_single_read(me_subdevice_t *subdevice, | ||
72 | struct file *filep, | ||
73 | int channel, | ||
74 | int *value, int time_out, int flags); | ||
75 | static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice, | ||
76 | struct file *filep, int flags); | ||
77 | static int me8200_di_query_number_channels(me_subdevice_t *subdevice, | ||
78 | int *number); | ||
79 | static int me8200_di_query_subdevice_type(me_subdevice_t *subdevice, | ||
80 | int *type, int *subtype); | ||
81 | static int me8200_di_query_subdevice_caps(me_subdevice_t *subdevice, | ||
82 | int *caps); | ||
83 | static irqreturn_t me8200_isr(int irq, void *dev_id); | ||
84 | static irqreturn_t me8200_isr_EX(int irq, void *dev_id); | ||
85 | static void me8200_di_check_version(me8200_di_subdevice_t *instance, | ||
86 | unsigned long addr); | ||
87 | |||
88 | ///Functions | ||
89 | static int me8200_di_io_irq_start(me_subdevice_t *subdevice, | ||
90 | struct file *filep, | ||
91 | int channel, | ||
92 | int irq_source, | ||
93 | int irq_edge, int irq_arg, int flags) | ||
94 | { | ||
95 | me8200_di_subdevice_t *instance; | ||
96 | int err = ME_ERRNO_SUCCESS; | ||
97 | volatile uint8_t tmp; | ||
98 | unsigned long status; | ||
99 | |||
100 | PDEBUG("executed.\n"); | ||
101 | |||
102 | instance = (me8200_di_subdevice_t *) subdevice; | ||
103 | |||
104 | if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { | ||
105 | if (flags & | ||
106 | ~(ME_IO_IRQ_START_PATTERN_FILTERING | | ||
107 | ME_IO_IRQ_START_DIO_BYTE)) { | ||
108 | PERROR("Invalid flag specified.\n"); | ||
109 | return ME_ERRNO_INVALID_FLAGS; | ||
110 | } | ||
111 | |||
112 | if (irq_edge != ME_IRQ_EDGE_NOT_USED) { | ||
113 | PERROR("Invalid irq edge specified.\n"); | ||
114 | return ME_ERRNO_INVALID_IRQ_EDGE; | ||
115 | } | ||
116 | } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { | ||
117 | if (flags & | ||
118 | ~(ME_IO_IRQ_START_EXTENDED_STATUS | | ||
119 | ME_IO_IRQ_START_DIO_BYTE)) { | ||
120 | PERROR("Invalid flag specified.\n"); | ||
121 | return ME_ERRNO_INVALID_FLAGS; | ||
122 | } | ||
123 | |||
124 | if ((irq_edge != ME_IRQ_EDGE_RISING) | ||
125 | && (irq_edge != ME_IRQ_EDGE_FALLING) | ||
126 | && (irq_edge != ME_IRQ_EDGE_ANY)) { | ||
127 | PERROR("Invalid irq edge specified.\n"); | ||
128 | return ME_ERRNO_INVALID_IRQ_EDGE; | ||
129 | } | ||
130 | |||
131 | if (!(irq_arg & 0xFF)) { | ||
132 | PERROR("No mask specified.\n"); | ||
133 | return ME_ERRNO_INVALID_IRQ_ARG; | ||
134 | } | ||
135 | } else { | ||
136 | PERROR("Invalid irq source specified.\n"); | ||
137 | return ME_ERRNO_INVALID_IRQ_SOURCE; | ||
138 | } | ||
139 | |||
140 | if (channel) { | ||
141 | PERROR("Invalid channel specified.\n"); | ||
142 | return ME_ERRNO_INVALID_CHANNEL; | ||
143 | } | ||
144 | |||
145 | ME_SUBDEVICE_ENTER; | ||
146 | |||
147 | spin_lock_irqsave(&instance->subdevice_lock, status); | ||
148 | if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { | ||
149 | outb(irq_arg, instance->compare_reg); | ||
150 | PDEBUG_REG("compare_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
151 | instance->reg_base, | ||
152 | instance->compare_reg - instance->reg_base, irq_arg); | ||
153 | outb(0xFF, instance->mask_reg); | ||
154 | PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
155 | instance->reg_base, | ||
156 | instance->mask_reg - instance->reg_base, 0xff); | ||
157 | instance->compare_value = irq_arg; | ||
158 | instance->filtering_flag = | ||
159 | (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0; | ||
160 | } | ||
161 | if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { | ||
162 | outb(irq_arg, instance->mask_reg); | ||
163 | PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
164 | instance->reg_base, | ||
165 | instance->mask_reg - instance->reg_base, irq_arg); | ||
166 | instance->filtering_flag = 0; | ||
167 | } | ||
168 | |||
169 | spin_lock(instance->irq_mode_lock); | ||
170 | tmp = inb(instance->irq_mode_reg); | ||
171 | tmp &= | ||
172 | ~(ME8200_IRQ_MODE_MASK << | ||
173 | (ME8200_IRQ_MODE_DI_SHIFT * instance->di_idx)); | ||
174 | if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { | ||
175 | tmp |= | ||
176 | ME8200_IRQ_MODE_MASK_COMPARE << (ME8200_IRQ_MODE_DI_SHIFT * | ||
177 | instance->di_idx); | ||
178 | } | ||
179 | |||
180 | if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { | ||
181 | tmp |= | ||
182 | ME8200_IRQ_MODE_MASK_MASK << (ME8200_IRQ_MODE_DI_SHIFT * | ||
183 | instance->di_idx); | ||
184 | } | ||
185 | outb(tmp, instance->irq_mode_reg); | ||
186 | PDEBUG_REG("irq_mode_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
187 | instance->irq_mode_reg - instance->reg_base, tmp); | ||
188 | spin_unlock(instance->irq_mode_lock); | ||
189 | |||
190 | spin_lock(instance->irq_ctrl_lock); | ||
191 | tmp = inb(instance->irq_ctrl_reg); | ||
192 | tmp |= | ||
193 | (ME8200_DI_IRQ_CTRL_BIT_CLEAR << | ||
194 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
195 | tmp |= | ||
196 | ME8200_DI_IRQ_CTRL_BIT_ENABLE << (ME8200_DI_IRQ_CTRL_SHIFT * | ||
197 | instance->di_idx); | ||
198 | |||
199 | if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { | ||
200 | tmp &= | ||
201 | ~(ME8200_DI_IRQ_CTRL_MASK_EDGE << | ||
202 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
203 | if (irq_edge == ME_IRQ_EDGE_RISING) { | ||
204 | tmp |= | ||
205 | ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING << | ||
206 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx); | ||
207 | } else if (irq_edge == ME_IRQ_EDGE_FALLING) { | ||
208 | tmp |= | ||
209 | ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING << | ||
210 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx); | ||
211 | } else if (irq_edge == ME_IRQ_EDGE_ANY) { | ||
212 | tmp |= | ||
213 | ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY << | ||
214 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx); | ||
215 | } | ||
216 | } | ||
217 | outb(tmp, instance->irq_ctrl_reg); | ||
218 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
219 | instance->irq_ctrl_reg - instance->reg_base, tmp); | ||
220 | tmp &= | ||
221 | ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << | ||
222 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
223 | outb(tmp, instance->irq_ctrl_reg); | ||
224 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
225 | instance->irq_ctrl_reg - instance->reg_base, tmp); | ||
226 | |||
227 | instance->line_value = inb(instance->port_reg); | ||
228 | spin_unlock(instance->irq_ctrl_lock); | ||
229 | |||
230 | instance->rised = 0; | ||
231 | instance->status_value = 0; | ||
232 | instance->status_value_edges = 0; | ||
233 | instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS; | ||
234 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
235 | ME_SUBDEVICE_EXIT; | ||
236 | |||
237 | return err; | ||
238 | } | ||
239 | |||
240 | static int me8200_di_io_irq_wait(me_subdevice_t *subdevice, | ||
241 | struct file *filep, | ||
242 | int channel, | ||
243 | int *irq_count, | ||
244 | int *value, int time_out, int flags) | ||
245 | { | ||
246 | me8200_di_subdevice_t *instance; | ||
247 | int err = ME_ERRNO_SUCCESS; | ||
248 | long t = 0; | ||
249 | unsigned long cpu_flags; | ||
250 | int count; | ||
251 | |||
252 | PDEBUG("executed.\n"); | ||
253 | PDEVELOP("PID: %d.\n", current->pid); | ||
254 | |||
255 | instance = (me8200_di_subdevice_t *) subdevice; | ||
256 | |||
257 | if (flags & | ||
258 | ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) { | ||
259 | PERROR("Invalid flag specified.\n"); | ||
260 | return ME_ERRNO_INVALID_FLAGS; | ||
261 | } | ||
262 | |||
263 | if (channel) { | ||
264 | PERROR("Invalid channel specified.\n"); | ||
265 | return ME_ERRNO_INVALID_CHANNEL; | ||
266 | } | ||
267 | |||
268 | if (time_out < 0) { | ||
269 | PERROR("Invalid time_out specified.\n"); | ||
270 | return ME_ERRNO_INVALID_TIMEOUT; | ||
271 | } | ||
272 | |||
273 | if (time_out) { | ||
274 | t = (time_out * HZ) / 1000; | ||
275 | |||
276 | if (t == 0) | ||
277 | t = 1; | ||
278 | } | ||
279 | |||
280 | ME_SUBDEVICE_ENTER; | ||
281 | |||
282 | if (instance->rised <= 0) { | ||
283 | instance->rised = 0; | ||
284 | count = instance->count; | ||
285 | |||
286 | if (time_out) { | ||
287 | t = wait_event_interruptible_timeout(instance-> | ||
288 | wait_queue, | ||
289 | ((count != | ||
290 | instance->count) | ||
291 | || (instance-> | ||
292 | rised < 0)), | ||
293 | t); | ||
294 | // t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t); | ||
295 | if (t == 0) { | ||
296 | PERROR("Wait on interrupt timed out.\n"); | ||
297 | err = ME_ERRNO_TIMEOUT; | ||
298 | } | ||
299 | } else { | ||
300 | wait_event_interruptible(instance->wait_queue, | ||
301 | ((count != instance->count) | ||
302 | || (instance->rised < 0))); | ||
303 | // wait_event_interruptible(instance->wait_queue, (instance->rised != 0)); | ||
304 | } | ||
305 | |||
306 | if (instance->rised < 0) { | ||
307 | PERROR("Wait on interrupt aborted by user.\n"); | ||
308 | err = ME_ERRNO_CANCELLED; | ||
309 | } | ||
310 | } | ||
311 | |||
312 | if (signal_pending(current)) { | ||
313 | PERROR("Wait on interrupt aborted by signal.\n"); | ||
314 | err = ME_ERRNO_SIGNAL; | ||
315 | } | ||
316 | |||
317 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
318 | *irq_count = instance->count; | ||
319 | if (!err) { | ||
320 | if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) { | ||
321 | *value = instance->status_value; | ||
322 | } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) { | ||
323 | *value = instance->status_value_edges; | ||
324 | } else { // Use default | ||
325 | if (!instance->status_flag) { | ||
326 | *value = instance->status_value; | ||
327 | } else { | ||
328 | *value = instance->status_value_edges; | ||
329 | } | ||
330 | } | ||
331 | instance->rised = 0; | ||
332 | /* | ||
333 | instance->status_value = 0; | ||
334 | instance->status_value_edges = 0; | ||
335 | */ | ||
336 | } else { | ||
337 | *value = 0; | ||
338 | } | ||
339 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
340 | |||
341 | ME_SUBDEVICE_EXIT; | ||
342 | |||
343 | return err; | ||
344 | } | ||
345 | |||
346 | static int me8200_di_io_irq_stop(me_subdevice_t *subdevice, | ||
347 | struct file *filep, int channel, int flags) | ||
348 | { | ||
349 | me8200_di_subdevice_t *instance; | ||
350 | uint8_t tmp; | ||
351 | unsigned long status; | ||
352 | |||
353 | PDEBUG("executed.\n"); | ||
354 | |||
355 | instance = (me8200_di_subdevice_t *) subdevice; | ||
356 | |||
357 | if (flags) { | ||
358 | PERROR("Invalid flag specified.\n"); | ||
359 | return ME_ERRNO_INVALID_FLAGS; | ||
360 | } | ||
361 | |||
362 | if (channel) { | ||
363 | PERROR("Invalid channel specified.\n"); | ||
364 | return ME_ERRNO_INVALID_CHANNEL; | ||
365 | } | ||
366 | |||
367 | ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status); | ||
368 | spin_lock(instance->irq_ctrl_lock); | ||
369 | tmp = inb(instance->irq_ctrl_reg); | ||
370 | tmp |= | ||
371 | (ME8200_DI_IRQ_CTRL_BIT_ENABLE << | ||
372 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
373 | outb(tmp, instance->irq_ctrl_reg); | ||
374 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
375 | instance->irq_ctrl_reg - instance->reg_base, tmp); | ||
376 | tmp &= | ||
377 | ~(ME8200_DI_IRQ_CTRL_BIT_ENABLE << | ||
378 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
379 | tmp |= | ||
380 | (ME8200_DI_IRQ_CTRL_BIT_CLEAR << | ||
381 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
382 | // tmp &= ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
383 | outb(tmp, instance->irq_ctrl_reg); | ||
384 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
385 | instance->irq_ctrl_reg - instance->reg_base, tmp); | ||
386 | spin_unlock(instance->irq_ctrl_lock); | ||
387 | |||
388 | instance->rised = -1; | ||
389 | instance->status_value = 0; | ||
390 | instance->status_value_edges = 0; | ||
391 | instance->filtering_flag = 0; | ||
392 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
393 | wake_up_interruptible_all(&instance->wait_queue); | ||
394 | |||
395 | ME_SUBDEVICE_EXIT; | ||
396 | |||
397 | return ME_ERRNO_SUCCESS; | ||
398 | } | ||
399 | |||
400 | static int me8200_di_io_single_config(me_subdevice_t *subdevice, | ||
401 | struct file *filep, | ||
402 | int channel, | ||
403 | int single_config, | ||
404 | int ref, | ||
405 | int trig_chan, | ||
406 | int trig_type, int trig_edge, int flags) | ||
407 | { | ||
408 | me8200_di_subdevice_t *instance; | ||
409 | int err = ME_ERRNO_SUCCESS; | ||
410 | unsigned long status; | ||
411 | |||
412 | PDEBUG("executed.\n"); | ||
413 | |||
414 | instance = (me8200_di_subdevice_t *) subdevice; | ||
415 | |||
416 | ME_SUBDEVICE_ENTER; | ||
417 | |||
418 | spin_lock_irqsave(&instance->subdevice_lock, status); | ||
419 | |||
420 | switch (flags) { | ||
421 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
422 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
423 | if (channel == 0) { | ||
424 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
425 | } else { | ||
426 | PERROR("Invalid port direction specified.\n"); | ||
427 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
428 | } | ||
429 | } else { | ||
430 | PERROR("Invalid channel number.\n"); | ||
431 | err = ME_ERRNO_INVALID_CHANNEL; | ||
432 | } | ||
433 | break; | ||
434 | |||
435 | default: | ||
436 | PERROR("Invalid flags specified.\n"); | ||
437 | err = ME_ERRNO_INVALID_FLAGS; | ||
438 | } | ||
439 | |||
440 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
441 | |||
442 | ME_SUBDEVICE_EXIT; | ||
443 | |||
444 | return err; | ||
445 | } | ||
446 | |||
447 | static int me8200_di_io_single_read(me_subdevice_t *subdevice, | ||
448 | struct file *filep, | ||
449 | int channel, | ||
450 | int *value, int time_out, int flags) | ||
451 | { | ||
452 | me8200_di_subdevice_t *instance; | ||
453 | int err = ME_ERRNO_SUCCESS; | ||
454 | unsigned long status; | ||
455 | |||
456 | PDEBUG("executed.\n"); | ||
457 | |||
458 | instance = (me8200_di_subdevice_t *) subdevice; | ||
459 | |||
460 | ME_SUBDEVICE_ENTER; | ||
461 | |||
462 | spin_lock_irqsave(&instance->subdevice_lock, status); | ||
463 | |||
464 | switch (flags) { | ||
465 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
466 | if ((channel >= 0) && (channel < 8)) { | ||
467 | *value = inb(instance->port_reg) & (0x1 << channel); | ||
468 | } else { | ||
469 | PERROR("Invalid bit number specified.\n"); | ||
470 | err = ME_ERRNO_INVALID_CHANNEL; | ||
471 | } | ||
472 | break; | ||
473 | |||
474 | case ME_IO_SINGLE_NO_FLAGS: | ||
475 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
476 | if (channel == 0) { | ||
477 | *value = inb(instance->port_reg); | ||
478 | } else { | ||
479 | PERROR("Invalid channel number.\n"); | ||
480 | err = ME_ERRNO_INVALID_CHANNEL; | ||
481 | } | ||
482 | break; | ||
483 | |||
484 | default: | ||
485 | PERROR("Invalid flags specified.\n"); | ||
486 | err = ME_ERRNO_INVALID_FLAGS; | ||
487 | } | ||
488 | |||
489 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
490 | |||
491 | ME_SUBDEVICE_EXIT; | ||
492 | |||
493 | return err; | ||
494 | } | ||
495 | |||
496 | static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice, | ||
497 | struct file *filep, int flags) | ||
498 | { | ||
499 | me8200_di_subdevice_t *instance = (me8200_di_subdevice_t *) subdevice; | ||
500 | |||
501 | PDEBUG("executed.\n"); | ||
502 | |||
503 | if (flags) { | ||
504 | PERROR("Invalid flag specified.\n"); | ||
505 | return ME_ERRNO_INVALID_FLAGS; | ||
506 | } | ||
507 | |||
508 | instance->count = 0; | ||
509 | return me8200_di_io_irq_stop(subdevice, filep, 0, 0); | ||
510 | } | ||
511 | |||
512 | static int me8200_di_query_number_channels(me_subdevice_t *subdevice, | ||
513 | int *number) | ||
514 | { | ||
515 | PDEBUG("executed.\n"); | ||
516 | *number = 8; | ||
517 | return ME_ERRNO_SUCCESS; | ||
518 | } | ||
519 | |||
520 | static int me8200_di_query_subdevice_type(me_subdevice_t *subdevice, | ||
521 | int *type, int *subtype) | ||
522 | { | ||
523 | PDEBUG("executed.\n"); | ||
524 | *type = ME_TYPE_DI; | ||
525 | *subtype = ME_SUBTYPE_SINGLE; | ||
526 | return ME_ERRNO_SUCCESS; | ||
527 | } | ||
528 | |||
529 | static int me8200_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
530 | { | ||
531 | PDEBUG("executed.\n"); | ||
532 | *caps = | ||
533 | ME_CAPS_DIO_BIT_PATTERN_IRQ | | ||
534 | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_RISING | | ||
535 | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_FALLING | | ||
536 | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY; | ||
537 | return ME_ERRNO_SUCCESS; | ||
538 | } | ||
539 | |||
540 | static irqreturn_t me8200_isr(int irq, void *dev_id) | ||
541 | { | ||
542 | me8200_di_subdevice_t *instance; | ||
543 | uint8_t ctrl; | ||
544 | uint8_t irq_status; | ||
545 | uint8_t line_value = 0; | ||
546 | uint8_t line_status = 0; | ||
547 | uint32_t status_val = 0; | ||
548 | |||
549 | instance = (me8200_di_subdevice_t *) dev_id; | ||
550 | |||
551 | if (irq != instance->irq) { | ||
552 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
553 | return IRQ_NONE; | ||
554 | } | ||
555 | |||
556 | irq_status = inb(instance->irq_status_reg); | ||
557 | if (!irq_status) { | ||
558 | PINFO | ||
559 | ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n", | ||
560 | jiffies, __func__, instance->di_idx, irq_status); | ||
561 | return IRQ_NONE; | ||
562 | } | ||
563 | |||
564 | PDEBUG("executed.\n"); | ||
565 | |||
566 | spin_lock(&instance->subdevice_lock); | ||
567 | spin_lock(instance->irq_ctrl_lock); | ||
568 | ctrl = inb(instance->irq_ctrl_reg); | ||
569 | ctrl |= | ||
570 | ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT * | ||
571 | instance->di_idx); | ||
572 | outb(ctrl, instance->irq_ctrl_reg); | ||
573 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
574 | instance->irq_ctrl_reg - instance->reg_base, ctrl); | ||
575 | ctrl &= | ||
576 | ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << | ||
577 | (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); | ||
578 | outb(ctrl, instance->irq_ctrl_reg); | ||
579 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
580 | instance->irq_ctrl_reg - instance->reg_base, ctrl); | ||
581 | |||
582 | line_value = inb(instance->port_reg); | ||
583 | spin_unlock(instance->irq_ctrl_lock); | ||
584 | |||
585 | line_status = ((uint8_t) instance->line_value ^ line_value); | ||
586 | |||
587 | // Make extended information. | ||
588 | status_val |= (0x00FF & (~(uint8_t) instance->line_value & line_value)) << 16; //Raise | ||
589 | status_val |= (0x00FF & ((uint8_t) instance->line_value & ~line_value)); //Fall | ||
590 | |||
591 | instance->line_value = (int)line_value; | ||
592 | |||
593 | if (instance->rised == 0) { | ||
594 | instance->status_value = irq_status | line_status; | ||
595 | instance->status_value_edges = status_val; | ||
596 | } else { | ||
597 | instance->status_value |= irq_status | line_status; | ||
598 | instance->status_value_edges |= status_val; | ||
599 | } | ||
600 | |||
601 | if (instance->filtering_flag) { // For compare mode only. | ||
602 | if (instance->compare_value == instance->line_value) { | ||
603 | instance->rised = 1; | ||
604 | instance->count++; | ||
605 | } | ||
606 | } else { | ||
607 | instance->rised = 1; | ||
608 | instance->count++; | ||
609 | } | ||
610 | spin_unlock(&instance->subdevice_lock); | ||
611 | |||
612 | spin_unlock(&instance->subdevice_lock); | ||
613 | |||
614 | wake_up_interruptible_all(&instance->wait_queue); | ||
615 | |||
616 | return IRQ_HANDLED; | ||
617 | } | ||
618 | |||
619 | static irqreturn_t me8200_isr_EX(int irq, void *dev_id) | ||
620 | { | ||
621 | me8200_di_subdevice_t *instance; | ||
622 | uint8_t irq_status = 0; | ||
623 | uint16_t irq_status_EX = 0; | ||
624 | uint32_t status_val = 0; | ||
625 | int i, j; | ||
626 | |||
627 | instance = (me8200_di_subdevice_t *) dev_id; | ||
628 | |||
629 | if (irq != instance->irq) { | ||
630 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
631 | return IRQ_NONE; | ||
632 | } | ||
633 | |||
634 | PDEBUG("executed.\n"); | ||
635 | |||
636 | //Reset latches. Copy status to extended registers. | ||
637 | irq_status = inb(instance->irq_status_reg); | ||
638 | PDEBUG_REG("idx=%d irq_status_reg=0x%02X\n", instance->di_idx, | ||
639 | irq_status); | ||
640 | |||
641 | if (!irq_status) { | ||
642 | PINFO | ||
643 | ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n", | ||
644 | jiffies, __func__, instance->di_idx, irq_status); | ||
645 | return IRQ_NONE; | ||
646 | } | ||
647 | |||
648 | irq_status_EX = inb(instance->irq_status_low_reg); | ||
649 | irq_status_EX |= (inb(instance->irq_status_high_reg) << 8); | ||
650 | |||
651 | PDEVELOP("EXTENDED REG: 0x%04x\n", irq_status_EX); | ||
652 | instance->line_value = inb(instance->port_reg); | ||
653 | |||
654 | // Format extended information. | ||
655 | for (i = 0, j = 0; i < 8; i++, j += 2) { | ||
656 | status_val |= ((0x01 << j) & irq_status_EX) >> (j - i); //Fall | ||
657 | status_val |= ((0x01 << (j + 1)) & irq_status_EX) << (15 - j + i); //Raise | ||
658 | } | ||
659 | |||
660 | spin_lock(&instance->subdevice_lock); | ||
661 | if (instance->rised == 0) { | ||
662 | instance->status_value = irq_status; | ||
663 | instance->status_value_edges = status_val; | ||
664 | } else { | ||
665 | instance->status_value |= irq_status; | ||
666 | instance->status_value_edges |= status_val; | ||
667 | } | ||
668 | |||
669 | if (instance->filtering_flag) { // For compare mode only. | ||
670 | if (instance->compare_value == instance->line_value) { | ||
671 | instance->rised = 1; | ||
672 | instance->count++; | ||
673 | } | ||
674 | } else { | ||
675 | instance->rised = 1; | ||
676 | instance->count++; | ||
677 | } | ||
678 | spin_unlock(&instance->subdevice_lock); | ||
679 | |||
680 | wake_up_interruptible_all(&instance->wait_queue); | ||
681 | |||
682 | return IRQ_HANDLED; | ||
683 | } | ||
684 | |||
685 | static void me8200_di_destructor(struct me_subdevice *subdevice) | ||
686 | { | ||
687 | me8200_di_subdevice_t *instance; | ||
688 | |||
689 | PDEBUG("executed.\n"); | ||
690 | |||
691 | instance = (me8200_di_subdevice_t *) subdevice; | ||
692 | |||
693 | free_irq(instance->irq, (void *)instance); | ||
694 | me_subdevice_deinit(&instance->base); | ||
695 | kfree(instance); | ||
696 | } | ||
697 | |||
698 | me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_regbase, | ||
699 | unsigned int di_idx, | ||
700 | int irq, | ||
701 | spinlock_t *irq_ctrl_lock, | ||
702 | spinlock_t *irq_mode_lock) | ||
703 | { | ||
704 | me8200_di_subdevice_t *subdevice; | ||
705 | int err; | ||
706 | |||
707 | PDEBUG("executed.\n"); | ||
708 | |||
709 | /* Allocate memory for subdevice instance */ | ||
710 | subdevice = kmalloc(sizeof(me8200_di_subdevice_t), GFP_KERNEL); | ||
711 | |||
712 | if (!subdevice) { | ||
713 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
714 | return NULL; | ||
715 | } | ||
716 | |||
717 | memset(subdevice, 0, sizeof(me8200_di_subdevice_t)); | ||
718 | |||
719 | /* Initialize subdevice base class */ | ||
720 | err = me_subdevice_init(&subdevice->base); | ||
721 | |||
722 | if (err) { | ||
723 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
724 | kfree(subdevice); | ||
725 | return NULL; | ||
726 | } | ||
727 | // Check firmware version. | ||
728 | me8200_di_check_version(subdevice, | ||
729 | me8200_regbase + ME8200_FIRMWARE_VERSION_REG); | ||
730 | |||
731 | // Initialize spin locks. | ||
732 | spin_lock_init(&subdevice->subdevice_lock); | ||
733 | |||
734 | subdevice->irq_ctrl_lock = irq_ctrl_lock; | ||
735 | subdevice->irq_mode_lock = irq_mode_lock; | ||
736 | |||
737 | /* Save the subdevice index. */ | ||
738 | subdevice->di_idx = di_idx; | ||
739 | |||
740 | /* Initialize registers */ | ||
741 | if (di_idx == 0) { | ||
742 | subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_0_REG; | ||
743 | subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_0_REG; | ||
744 | subdevice->compare_reg = | ||
745 | me8200_regbase + ME8200_DI_COMPARE_0_REG; | ||
746 | subdevice->irq_status_reg = | ||
747 | me8200_regbase + ME8200_DI_CHANGE_0_REG; | ||
748 | |||
749 | subdevice->irq_status_low_reg = | ||
750 | me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_LOW_REG; | ||
751 | subdevice->irq_status_high_reg = | ||
752 | me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_HIGH_REG; | ||
753 | } else if (di_idx == 1) { | ||
754 | subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_1_REG; | ||
755 | subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_1_REG; | ||
756 | subdevice->compare_reg = | ||
757 | me8200_regbase + ME8200_DI_COMPARE_1_REG; | ||
758 | subdevice->irq_status_reg = | ||
759 | me8200_regbase + ME8200_DI_CHANGE_1_REG; | ||
760 | |||
761 | subdevice->irq_status_low_reg = | ||
762 | me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_LOW_REG; | ||
763 | subdevice->irq_status_high_reg = | ||
764 | me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_HIGH_REG; | ||
765 | } else { | ||
766 | PERROR("Wrong subdevice idx=%d.\n", di_idx); | ||
767 | kfree(subdevice); | ||
768 | return NULL; | ||
769 | } | ||
770 | subdevice->irq_ctrl_reg = me8200_regbase + ME8200_DI_IRQ_CTRL_REG; | ||
771 | subdevice->irq_mode_reg = me8200_regbase + ME8200_IRQ_MODE_REG; | ||
772 | #ifdef MEDEBUG_DEBUG_REG | ||
773 | subdevice->reg_base = me8200_regbase; | ||
774 | #endif | ||
775 | |||
776 | /* Initialize wait queue */ | ||
777 | init_waitqueue_head(&subdevice->wait_queue); | ||
778 | |||
779 | /* Overload base class methods. */ | ||
780 | subdevice->base.me_subdevice_io_irq_start = me8200_di_io_irq_start; | ||
781 | subdevice->base.me_subdevice_io_irq_wait = me8200_di_io_irq_wait; | ||
782 | subdevice->base.me_subdevice_io_irq_stop = me8200_di_io_irq_stop; | ||
783 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
784 | me8200_di_io_reset_subdevice; | ||
785 | subdevice->base.me_subdevice_io_single_config = | ||
786 | me8200_di_io_single_config; | ||
787 | subdevice->base.me_subdevice_io_single_read = me8200_di_io_single_read; | ||
788 | subdevice->base.me_subdevice_query_number_channels = | ||
789 | me8200_di_query_number_channels; | ||
790 | subdevice->base.me_subdevice_query_subdevice_type = | ||
791 | me8200_di_query_subdevice_type; | ||
792 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
793 | me8200_di_query_subdevice_caps; | ||
794 | subdevice->base.me_subdevice_destructor = me8200_di_destructor; | ||
795 | |||
796 | subdevice->rised = 0; | ||
797 | subdevice->count = 0; | ||
798 | |||
799 | /* Register interrupt service routine. */ | ||
800 | subdevice->irq = irq; | ||
801 | if (subdevice->version > 0) { // NEW | ||
802 | err = request_irq(subdevice->irq, me8200_isr_EX, | ||
803 | IRQF_DISABLED | IRQF_SHARED, | ||
804 | ME8200_NAME, (void *)subdevice); | ||
805 | } else { //OLD | ||
806 | err = request_irq(subdevice->irq, me8200_isr, | ||
807 | IRQF_DISABLED | IRQF_SHARED, | ||
808 | ME8200_NAME, (void *)subdevice); | ||
809 | } | ||
810 | |||
811 | if (err) { | ||
812 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
813 | kfree(subdevice); | ||
814 | return NULL; | ||
815 | } | ||
816 | PDEBUG("Registred irq=%d.\n", subdevice->irq); | ||
817 | |||
818 | return subdevice; | ||
819 | } | ||
820 | |||
821 | static void me8200_di_check_version(me8200_di_subdevice_t *instance, | ||
822 | unsigned long addr) | ||
823 | { | ||
824 | |||
825 | PDEBUG("executed.\n"); | ||
826 | instance->version = 0x000000FF & inb(addr); | ||
827 | PDEVELOP("me8200 firmware version: %d\n", instance->version); | ||
828 | |||
829 | /// @note Fix for wrong values in this registry. | ||
830 | if ((instance->version < 0x7) || (instance->version > 0x1F)) | ||
831 | instance->version = 0x0; | ||
832 | } | ||
diff --git a/drivers/staging/meilhaus/me8200_di.h b/drivers/staging/meilhaus/me8200_di.h deleted file mode 100644 index 2a3b005b67d4..000000000000 --- a/drivers/staging/meilhaus/me8200_di.h +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_di.h | ||
3 | * | ||
4 | * @brief ME-8200 digital input subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_DI_H_ | ||
28 | #define _ME8200_DI_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me8200_di_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; | ||
44 | spinlock_t *irq_ctrl_lock; | ||
45 | spinlock_t *irq_mode_lock; | ||
46 | |||
47 | unsigned int di_idx; | ||
48 | unsigned int version; | ||
49 | |||
50 | int irq; /**< The number of the interrupt request. */ | ||
51 | volatile int rised; /**< Flag to indicate if an interrupt occured. */ | ||
52 | uint status_flag; /**< Default interupt status flag */ | ||
53 | uint status_value; /**< Interupt status */ | ||
54 | uint status_value_edges; /**< Extended interupt status */ | ||
55 | uint line_value; | ||
56 | int count; /**< Counts the number of interrupts occured. */ | ||
57 | uint8_t compare_value; | ||
58 | uint8_t filtering_flag; | ||
59 | |||
60 | wait_queue_head_t wait_queue; /**< To wait on interrupts. */ | ||
61 | |||
62 | unsigned long port_reg; /**< The digital input port. */ | ||
63 | unsigned long compare_reg; /**< The register to hold the value to compare with. */ | ||
64 | unsigned long mask_reg; /**< The register to hold the mask. */ | ||
65 | unsigned long irq_mode_reg; /**< The interrupt mode register. */ | ||
66 | unsigned long irq_ctrl_reg; /**< The interrupt control register. */ | ||
67 | unsigned long irq_status_reg; /**< The interrupt status register. Also interrupt reseting register (firmware version 7 and later).*/ | ||
68 | #ifdef MEDEBUG_DEBUG_REG | ||
69 | unsigned long reg_base; | ||
70 | #endif | ||
71 | unsigned long firmware_version_reg; /**< The interrupt reseting register. */ | ||
72 | |||
73 | unsigned long irq_status_low_reg; /**< The interrupt extended status register (low part). */ | ||
74 | unsigned long irq_status_high_reg; /**< The interrupt extended status register (high part). */ | ||
75 | } me8200_di_subdevice_t; | ||
76 | |||
77 | /** | ||
78 | * @brief The constructor to generate a ME-8200 digital input subdevice instance. | ||
79 | * | ||
80 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
81 | * | ||
82 | * @return Pointer to new instance on success.\n | ||
83 | * NULL on error. | ||
84 | */ | ||
85 | me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_reg_base, | ||
86 | unsigned int di_idx, | ||
87 | int irq, | ||
88 | spinlock_t * irq_ctrl_lock, | ||
89 | spinlock_t * irq_mode_lock); | ||
90 | |||
91 | #endif | ||
92 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_di_reg.h b/drivers/staging/meilhaus/me8200_di_reg.h deleted file mode 100644 index b9a619d31c2c..000000000000 --- a/drivers/staging/meilhaus/me8200_di_reg.h +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_di_reg.h | ||
3 | * | ||
4 | * @brief ME-8200 digital input subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_DI_REG_H_ | ||
28 | #define _ME8200_DI_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | // Common registry for whole family. | ||
33 | #define ME8200_DI_PORT_0_REG 0x3 // R | ||
34 | #define ME8200_DI_PORT_1_REG 0x4 // R | ||
35 | |||
36 | #define ME8200_DI_MASK_0_REG 0x5 // R/W | ||
37 | #define ME8200_DI_MASK_1_REG 0x6 // R/W | ||
38 | |||
39 | #define ME8200_DI_COMPARE_0_REG 0xA // R/W | ||
40 | #define ME8200_DI_COMPARE_1_REG 0xB // R/W | ||
41 | |||
42 | #define ME8200_DI_IRQ_CTRL_REG 0xC // R/W | ||
43 | |||
44 | #ifndef ME8200_IRQ_MODE_REG | ||
45 | # define ME8200_IRQ_MODE_REG 0xD // R/W | ||
46 | #endif | ||
47 | |||
48 | // This registry are for all versions | ||
49 | #define ME8200_DI_CHANGE_0_REG 0xE // R | ||
50 | #define ME8200_DI_CHANGE_1_REG 0xF // R | ||
51 | |||
52 | #define ME8200_DI_IRQ_CTRL_BIT_CLEAR 0x4 | ||
53 | #define ME8200_DI_IRQ_CTRL_BIT_ENABLE 0x8 | ||
54 | |||
55 | // This registry are for firmware versions 7 and later | ||
56 | #define ME8200_DI_EXTEND_CHANGE_0_LOW_REG 0x10 // R | ||
57 | #define ME8200_DI_EXTEND_CHANGE_0_HIGH_REG 0x11 // R | ||
58 | #define ME8200_DI_EXTEND_CHANGE_1_LOW_REG 0x12 // R | ||
59 | #define ME8200_DI_EXTEND_CHANGE_1_HIGH_REG 0x13 // R | ||
60 | |||
61 | #ifndef ME8200_FIRMWARE_VERSION_REG | ||
62 | # define ME8200_FIRMWARE_VERSION_REG 0x14 // R | ||
63 | #endif | ||
64 | |||
65 | // Bit definitions | ||
66 | #define ME8200_DI_IRQ_CTRL_MASK_EDGE 0x3 | ||
67 | #define ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING 0x0 | ||
68 | #define ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING 0x1 | ||
69 | #define ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY 0x3 | ||
70 | |||
71 | // Others | ||
72 | #define ME8200_DI_IRQ_CTRL_SHIFT 4 | ||
73 | |||
74 | #endif | ||
75 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_dio.c b/drivers/staging/meilhaus/me8200_dio.c deleted file mode 100644 index c7f43f011f3c..000000000000 --- a/drivers/staging/meilhaus/me8200_dio.c +++ /dev/null | |||
@@ -1,418 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_dio.c | ||
3 | * | ||
4 | * @brief ME-8200 digital input/output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/io.h> | ||
40 | #include <linux/types.h> | ||
41 | |||
42 | #include "medefines.h" | ||
43 | #include "meinternal.h" | ||
44 | #include "meerror.h" | ||
45 | |||
46 | #include "medebug.h" | ||
47 | #include "me8200_dio_reg.h" | ||
48 | #include "me8200_dio.h" | ||
49 | |||
50 | /* | ||
51 | * Defines | ||
52 | */ | ||
53 | |||
54 | /* | ||
55 | * Functions | ||
56 | */ | ||
57 | |||
58 | static int me8200_dio_io_reset_subdevice(struct me_subdevice *subdevice, | ||
59 | struct file *filep, int flags) | ||
60 | { | ||
61 | me8200_dio_subdevice_t *instance; | ||
62 | uint8_t mode; | ||
63 | |||
64 | PDEBUG("executed.\n"); | ||
65 | |||
66 | if (flags) { | ||
67 | PERROR("Invalid flag specified.\n"); | ||
68 | return ME_ERRNO_INVALID_FLAGS; | ||
69 | } | ||
70 | |||
71 | instance = (me8200_dio_subdevice_t *) subdevice; | ||
72 | |||
73 | ME_SUBDEVICE_ENTER; | ||
74 | |||
75 | spin_lock(&instance->subdevice_lock); | ||
76 | spin_lock(instance->ctrl_reg_lock); | ||
77 | mode = inb(instance->ctrl_reg); | ||
78 | mode &= ~(0x3 << (instance->dio_idx * 2)); | ||
79 | outb(mode, instance->ctrl_reg); | ||
80 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
81 | instance->ctrl_reg - instance->reg_base, mode); | ||
82 | spin_unlock(instance->ctrl_reg_lock); | ||
83 | outb(0x00, instance->port_reg); | ||
84 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
85 | instance->port_reg - instance->reg_base, 0x00); | ||
86 | spin_unlock(&instance->subdevice_lock); | ||
87 | |||
88 | ME_SUBDEVICE_EXIT; | ||
89 | |||
90 | return ME_ERRNO_SUCCESS; | ||
91 | } | ||
92 | |||
93 | static int me8200_dio_io_single_config(me_subdevice_t *subdevice, | ||
94 | struct file *filep, | ||
95 | int channel, | ||
96 | int single_config, | ||
97 | int ref, | ||
98 | int trig_chan, | ||
99 | int trig_type, int trig_edge, int flags) | ||
100 | { | ||
101 | me8200_dio_subdevice_t *instance; | ||
102 | int err = ME_ERRNO_SUCCESS; | ||
103 | uint32_t mode; | ||
104 | uint32_t size = | ||
105 | flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE | ||
106 | | ME_IO_SINGLE_CONFIG_DIO_WORD | | ||
107 | ME_IO_SINGLE_CONFIG_DIO_DWORD); | ||
108 | |||
109 | PDEBUG("executed.\n"); | ||
110 | |||
111 | instance = (me8200_dio_subdevice_t *) subdevice; | ||
112 | |||
113 | ME_SUBDEVICE_ENTER; | ||
114 | |||
115 | spin_lock(&instance->subdevice_lock); | ||
116 | spin_lock(instance->ctrl_reg_lock); | ||
117 | mode = inb(instance->ctrl_reg); | ||
118 | switch (size) { | ||
119 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
120 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
121 | if (channel == 0) { | ||
122 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
123 | mode &= | ||
124 | ~((ME8200_DIO_CTRL_BIT_MODE_0 | | ||
125 | ME8200_DIO_CTRL_BIT_MODE_1) << | ||
126 | (instance->dio_idx * 2)); | ||
127 | } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
128 | mode &= | ||
129 | ~((ME8200_DIO_CTRL_BIT_MODE_0 | | ||
130 | ME8200_DIO_CTRL_BIT_MODE_1) << | ||
131 | (instance->dio_idx * 2)); | ||
132 | mode |= | ||
133 | ME8200_DIO_CTRL_BIT_MODE_0 << (instance-> | ||
134 | dio_idx * 2); | ||
135 | } else { | ||
136 | PERROR | ||
137 | ("Invalid port configuration specified.\n"); | ||
138 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
139 | } | ||
140 | } else { | ||
141 | PERROR("Invalid channel number.\n"); | ||
142 | err = ME_ERRNO_INVALID_CHANNEL; | ||
143 | } | ||
144 | |||
145 | break; | ||
146 | |||
147 | default: | ||
148 | PERROR("Invalid flags.\n"); | ||
149 | |||
150 | err = ME_ERRNO_INVALID_FLAGS; | ||
151 | } | ||
152 | |||
153 | if (!err) { | ||
154 | outb(mode, instance->ctrl_reg); | ||
155 | PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
156 | instance->reg_base, | ||
157 | instance->ctrl_reg - instance->reg_base, mode); | ||
158 | } | ||
159 | spin_unlock(instance->ctrl_reg_lock); | ||
160 | spin_unlock(&instance->subdevice_lock); | ||
161 | |||
162 | ME_SUBDEVICE_EXIT; | ||
163 | |||
164 | return err; | ||
165 | } | ||
166 | |||
167 | static int me8200_dio_io_single_read(me_subdevice_t *subdevice, | ||
168 | struct file *filep, | ||
169 | int channel, | ||
170 | int *value, int time_out, int flags) | ||
171 | { | ||
172 | me8200_dio_subdevice_t *instance; | ||
173 | int err = ME_ERRNO_SUCCESS; | ||
174 | uint8_t mode; | ||
175 | |||
176 | PDEBUG("executed.\n"); | ||
177 | |||
178 | instance = (me8200_dio_subdevice_t *) subdevice; | ||
179 | |||
180 | ME_SUBDEVICE_ENTER; | ||
181 | |||
182 | spin_lock(&instance->subdevice_lock); | ||
183 | spin_lock(instance->ctrl_reg_lock); | ||
184 | switch (flags) { | ||
185 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
186 | if ((channel >= 0) && (channel < 8)) { | ||
187 | mode = | ||
188 | inb(instance-> | ||
189 | ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | | ||
190 | ME8200_DIO_CTRL_BIT_MODE_1) << | ||
191 | (instance->dio_idx * 2)); | ||
192 | |||
193 | if ((mode == | ||
194 | (ME8200_DIO_CTRL_BIT_MODE_0 << | ||
195 | (instance->dio_idx * 2))) || !mode) { | ||
196 | *value = | ||
197 | inb(instance-> | ||
198 | port_reg) & (0x0001 << channel); | ||
199 | } else { | ||
200 | PERROR("Port not in output or input mode.\n"); | ||
201 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
202 | } | ||
203 | } else { | ||
204 | PERROR("Invalid bit number specified.\n"); | ||
205 | err = ME_ERRNO_INVALID_CHANNEL; | ||
206 | } | ||
207 | break; | ||
208 | |||
209 | case ME_IO_SINGLE_NO_FLAGS: | ||
210 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
211 | if (channel == 0) { | ||
212 | mode = | ||
213 | inb(instance-> | ||
214 | ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | | ||
215 | ME8200_DIO_CTRL_BIT_MODE_1) << | ||
216 | (instance->dio_idx * 2)); | ||
217 | |||
218 | if ((mode == | ||
219 | (ME8200_DIO_CTRL_BIT_MODE_0 << | ||
220 | (instance->dio_idx * 2))) || !mode) { | ||
221 | *value = inb(instance->port_reg) & 0x00FF; | ||
222 | } else { | ||
223 | PERROR("Port not in output or input mode.\n"); | ||
224 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
225 | } | ||
226 | } else { | ||
227 | PERROR("Invalid byte number specified.\n"); | ||
228 | err = ME_ERRNO_INVALID_CHANNEL; | ||
229 | } | ||
230 | break; | ||
231 | |||
232 | default: | ||
233 | PERROR("Invalid flags specified.\n"); | ||
234 | err = ME_ERRNO_INVALID_FLAGS; | ||
235 | } | ||
236 | spin_unlock(instance->ctrl_reg_lock); | ||
237 | spin_unlock(&instance->subdevice_lock); | ||
238 | |||
239 | ME_SUBDEVICE_EXIT; | ||
240 | |||
241 | return err; | ||
242 | } | ||
243 | |||
244 | static int me8200_dio_io_single_write(me_subdevice_t *subdevice, | ||
245 | struct file *filep, | ||
246 | int channel, | ||
247 | int value, int time_out, int flags) | ||
248 | { | ||
249 | me8200_dio_subdevice_t *instance; | ||
250 | int err = ME_ERRNO_SUCCESS; | ||
251 | uint8_t mode; | ||
252 | uint8_t byte; | ||
253 | |||
254 | PDEBUG("executed.\n"); | ||
255 | |||
256 | instance = (me8200_dio_subdevice_t *) subdevice; | ||
257 | |||
258 | ME_SUBDEVICE_ENTER; | ||
259 | |||
260 | spin_lock(&instance->subdevice_lock); | ||
261 | spin_lock(instance->ctrl_reg_lock); | ||
262 | switch (flags) { | ||
263 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
264 | if ((channel >= 0) && (channel < 8)) { | ||
265 | mode = | ||
266 | inb(instance-> | ||
267 | ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | | ||
268 | ME8200_DIO_CTRL_BIT_MODE_1) << | ||
269 | (instance->dio_idx * 2)); | ||
270 | |||
271 | if (mode == | ||
272 | (ME8200_DIO_CTRL_BIT_MODE_0 << | ||
273 | (instance->dio_idx * 2))) { | ||
274 | byte = inb(instance->port_reg); | ||
275 | |||
276 | if (value) | ||
277 | byte |= 0x1 << channel; | ||
278 | else | ||
279 | byte &= ~(0x1 << channel); | ||
280 | |||
281 | outb(byte, instance->port_reg); | ||
282 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
283 | instance->reg_base, | ||
284 | instance->port_reg - | ||
285 | instance->reg_base, byte); | ||
286 | } else { | ||
287 | PERROR("Port not in output or input mode.\n"); | ||
288 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
289 | } | ||
290 | } else { | ||
291 | PERROR("Invalid bit number specified.\n"); | ||
292 | err = ME_ERRNO_INVALID_CHANNEL; | ||
293 | } | ||
294 | break; | ||
295 | |||
296 | case ME_IO_SINGLE_NO_FLAGS: | ||
297 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
298 | if (channel == 0) { | ||
299 | mode = | ||
300 | inb(instance-> | ||
301 | ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | | ||
302 | ME8200_DIO_CTRL_BIT_MODE_1) << | ||
303 | (instance->dio_idx * 2)); | ||
304 | |||
305 | if (mode == | ||
306 | (ME8200_DIO_CTRL_BIT_MODE_0 << | ||
307 | (instance->dio_idx * 2))) { | ||
308 | outb(value, instance->port_reg); | ||
309 | PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", | ||
310 | instance->reg_base, | ||
311 | instance->port_reg - | ||
312 | instance->reg_base, value); | ||
313 | } else { | ||
314 | PERROR("Port not in output or input mode.\n"); | ||
315 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
316 | } | ||
317 | } else { | ||
318 | PERROR("Invalid byte number specified.\n"); | ||
319 | err = ME_ERRNO_INVALID_CHANNEL; | ||
320 | } | ||
321 | break; | ||
322 | |||
323 | default: | ||
324 | PERROR("Invalid flags specified.\n"); | ||
325 | err = ME_ERRNO_INVALID_FLAGS; | ||
326 | } | ||
327 | spin_unlock(instance->ctrl_reg_lock); | ||
328 | spin_unlock(&instance->subdevice_lock); | ||
329 | |||
330 | ME_SUBDEVICE_EXIT; | ||
331 | |||
332 | return err; | ||
333 | } | ||
334 | |||
335 | static int me8200_dio_query_number_channels(me_subdevice_t *subdevice, | ||
336 | int *number) | ||
337 | { | ||
338 | PDEBUG("executed.\n"); | ||
339 | *number = 8; | ||
340 | return ME_ERRNO_SUCCESS; | ||
341 | } | ||
342 | |||
343 | static int me8200_dio_query_subdevice_type(me_subdevice_t *subdevice, | ||
344 | int *type, int *subtype) | ||
345 | { | ||
346 | PDEBUG("executed.\n"); | ||
347 | *type = ME_TYPE_DIO; | ||
348 | *subtype = ME_SUBTYPE_SINGLE; | ||
349 | return ME_ERRNO_SUCCESS; | ||
350 | } | ||
351 | |||
352 | static int me8200_dio_query_subdevice_caps(me_subdevice_t *subdevice, | ||
353 | int *caps) | ||
354 | { | ||
355 | PDEBUG("executed.\n"); | ||
356 | *caps = ME_CAPS_DIO_DIR_BYTE; | ||
357 | return ME_ERRNO_SUCCESS; | ||
358 | } | ||
359 | |||
360 | me8200_dio_subdevice_t *me8200_dio_constructor(uint32_t reg_base, | ||
361 | unsigned int dio_idx, | ||
362 | spinlock_t *ctrl_reg_lock) | ||
363 | { | ||
364 | me8200_dio_subdevice_t *subdevice; | ||
365 | int err; | ||
366 | |||
367 | PDEBUG("executed.\n"); | ||
368 | |||
369 | /* Allocate memory for subdevice instance */ | ||
370 | subdevice = kmalloc(sizeof(me8200_dio_subdevice_t), GFP_KERNEL); | ||
371 | |||
372 | if (!subdevice) { | ||
373 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
374 | return NULL; | ||
375 | } | ||
376 | |||
377 | memset(subdevice, 0, sizeof(me8200_dio_subdevice_t)); | ||
378 | |||
379 | /* Initialize subdevice base class */ | ||
380 | err = me_subdevice_init(&subdevice->base); | ||
381 | |||
382 | if (err) { | ||
383 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
384 | kfree(subdevice); | ||
385 | return NULL; | ||
386 | } | ||
387 | // Initialize spin locks. | ||
388 | spin_lock_init(&subdevice->subdevice_lock); | ||
389 | |||
390 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
391 | |||
392 | /* Save digital i/o index */ | ||
393 | subdevice->dio_idx = dio_idx; | ||
394 | |||
395 | /* Save the subdevice index */ | ||
396 | subdevice->ctrl_reg = reg_base + ME8200_DIO_CTRL_REG; | ||
397 | subdevice->port_reg = reg_base + ME8200_DIO_PORT_REG + dio_idx; | ||
398 | #ifdef MEDEBUG_DEBUG_REG | ||
399 | subdevice->reg_base = reg_base; | ||
400 | #endif | ||
401 | |||
402 | /* Overload base class methods. */ | ||
403 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
404 | me8200_dio_io_reset_subdevice; | ||
405 | subdevice->base.me_subdevice_io_single_config = | ||
406 | me8200_dio_io_single_config; | ||
407 | subdevice->base.me_subdevice_io_single_read = me8200_dio_io_single_read; | ||
408 | subdevice->base.me_subdevice_io_single_write = | ||
409 | me8200_dio_io_single_write; | ||
410 | subdevice->base.me_subdevice_query_number_channels = | ||
411 | me8200_dio_query_number_channels; | ||
412 | subdevice->base.me_subdevice_query_subdevice_type = | ||
413 | me8200_dio_query_subdevice_type; | ||
414 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
415 | me8200_dio_query_subdevice_caps; | ||
416 | |||
417 | return subdevice; | ||
418 | } | ||
diff --git a/drivers/staging/meilhaus/me8200_dio.h b/drivers/staging/meilhaus/me8200_dio.h deleted file mode 100644 index 9ddd93d26f15..000000000000 --- a/drivers/staging/meilhaus/me8200_dio.h +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_dio.h | ||
3 | * | ||
4 | * @brief ME-8200 digital input/output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_DIO_H_ | ||
28 | #define _ME8200_DIO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me8200_dio_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | unsigned int dio_idx; /**< The index of the digital i/o on the device. */ | ||
45 | |||
46 | unsigned long port_reg; /**< Register holding the port status. */ | ||
47 | unsigned long ctrl_reg; /**< Register to configure the port direction. */ | ||
48 | #ifdef MEDEBUG_DEBUG_REG | ||
49 | unsigned long reg_base; | ||
50 | #endif | ||
51 | } me8200_dio_subdevice_t; | ||
52 | |||
53 | /** | ||
54 | * @brief The constructor to generate a ME-8200 digital input/ouput subdevice instance. | ||
55 | * | ||
56 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
57 | * @param dio_idx The index of the digital i/o port on the device. | ||
58 | * @param ctrl_reg_lock Spin lock protecting the control register. | ||
59 | * | ||
60 | * @return Pointer to new instance on success.\n | ||
61 | * NULL on error. | ||
62 | */ | ||
63 | me8200_dio_subdevice_t *me8200_dio_constructor(uint32_t reg_base, | ||
64 | unsigned int dio_idx, | ||
65 | spinlock_t * ctrl_reg_lock); | ||
66 | |||
67 | #endif | ||
68 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_dio_reg.h b/drivers/staging/meilhaus/me8200_dio_reg.h deleted file mode 100644 index ac94a133abaf..000000000000 --- a/drivers/staging/meilhaus/me8200_dio_reg.h +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_dio_reg.h | ||
3 | * | ||
4 | * @brief ME-8200 digital input/output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_DIO_REG_H_ | ||
28 | #define _ME8200_DIO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME8200_DIO_CTRL_REG 0x7 // R/W | ||
33 | #define ME8200_DIO_PORT_0_REG 0x8 // R/W | ||
34 | #define ME8200_DIO_PORT_1_REG 0x9 // R/W | ||
35 | #define ME8200_DIO_PORT_REG ME8200_DIO_PORT_0_REG // R/W | ||
36 | |||
37 | #define ME8200_DIO_CTRL_BIT_MODE_0 0x01 | ||
38 | #define ME8200_DIO_CTRL_BIT_MODE_1 0x02 | ||
39 | #define ME8200_DIO_CTRL_BIT_MODE_2 0x04 | ||
40 | #define ME8200_DIO_CTRL_BIT_MODE_3 0x08 | ||
41 | |||
42 | #endif | ||
43 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_do.c b/drivers/staging/meilhaus/me8200_do.c deleted file mode 100644 index e42a137617a1..000000000000 --- a/drivers/staging/meilhaus/me8200_do.c +++ /dev/null | |||
@@ -1,591 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_do.c | ||
3 | * | ||
4 | * @brief ME-8200 digital output subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | /* | ||
33 | * Includes | ||
34 | */ | ||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/slab.h> | ||
38 | #include <linux/spinlock.h> | ||
39 | #include <linux/interrupt.h> | ||
40 | #include <linux/io.h> | ||
41 | #include <linux/types.h> | ||
42 | |||
43 | #include "medefines.h" | ||
44 | #include "meinternal.h" | ||
45 | #include "meerror.h" | ||
46 | |||
47 | #include "meids.h" | ||
48 | #include "medebug.h" | ||
49 | #include "me8200_reg.h" | ||
50 | #include "me8200_do_reg.h" | ||
51 | #include "me8200_do.h" | ||
52 | |||
53 | /* | ||
54 | * Defines | ||
55 | */ | ||
56 | |||
57 | /* | ||
58 | * Functions | ||
59 | */ | ||
60 | |||
61 | static int me8200_do_io_irq_start(me_subdevice_t *subdevice, | ||
62 | struct file *filep, | ||
63 | int channel, | ||
64 | int irq_source, | ||
65 | int irq_edge, int irq_arg, int flags) | ||
66 | { | ||
67 | me8200_do_subdevice_t *instance; | ||
68 | int err = ME_ERRNO_SUCCESS; | ||
69 | uint8_t tmp; | ||
70 | unsigned long status; | ||
71 | |||
72 | if (flags & ~ME_IO_IRQ_START_DIO_BYTE) { | ||
73 | PERROR("Invalid flag specified.\n"); | ||
74 | return ME_ERRNO_INVALID_FLAGS; | ||
75 | } | ||
76 | |||
77 | if (channel != 0) { | ||
78 | PERROR("Invalid channel specified.\n"); | ||
79 | return ME_ERRNO_INVALID_CHANNEL; | ||
80 | } | ||
81 | |||
82 | if (irq_source != ME_IRQ_SOURCE_DIO_OVER_TEMP) { | ||
83 | PERROR("Invalid interrupt source specified.\n"); | ||
84 | return ME_ERRNO_INVALID_IRQ_SOURCE; | ||
85 | } | ||
86 | |||
87 | PDEBUG("executed.\n"); | ||
88 | |||
89 | instance = (me8200_do_subdevice_t *) subdevice; | ||
90 | |||
91 | ME_SUBDEVICE_ENTER; | ||
92 | |||
93 | spin_lock_irqsave(&instance->subdevice_lock, status); | ||
94 | spin_lock(instance->irq_mode_lock); | ||
95 | tmp = inb(instance->irq_ctrl_reg); | ||
96 | tmp |= | ||
97 | ME8200_IRQ_MODE_BIT_ENABLE_POWER << (ME8200_IRQ_MODE_POWER_SHIFT * | ||
98 | instance->do_idx); | ||
99 | outb(tmp, instance->irq_ctrl_reg); | ||
100 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
101 | instance->irq_ctrl_reg - instance->reg_base, tmp); | ||
102 | spin_unlock(instance->irq_mode_lock); | ||
103 | instance->rised = 0; | ||
104 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
105 | |||
106 | ME_SUBDEVICE_EXIT; | ||
107 | |||
108 | return err; | ||
109 | } | ||
110 | |||
111 | static int me8200_do_io_irq_wait(me_subdevice_t *subdevice, | ||
112 | struct file *filep, | ||
113 | int channel, | ||
114 | int *irq_count, | ||
115 | int *value, int time_out, int flags) | ||
116 | { | ||
117 | me8200_do_subdevice_t *instance; | ||
118 | int err = ME_ERRNO_SUCCESS; | ||
119 | long t = 0; | ||
120 | unsigned long cpu_flags; | ||
121 | |||
122 | PDEBUG("executed.\n"); | ||
123 | |||
124 | instance = (me8200_do_subdevice_t *) subdevice; | ||
125 | |||
126 | if (flags) { | ||
127 | PERROR("Invalid flag specified.\n"); | ||
128 | return ME_ERRNO_INVALID_FLAGS; | ||
129 | } | ||
130 | |||
131 | if (time_out < 0) { | ||
132 | PERROR("Invalid time_out specified.\n"); | ||
133 | return ME_ERRNO_INVALID_TIMEOUT; | ||
134 | } | ||
135 | |||
136 | if (time_out) { | ||
137 | t = (time_out * HZ) / 1000; | ||
138 | |||
139 | if (t == 0) | ||
140 | t = 1; | ||
141 | } | ||
142 | |||
143 | ME_SUBDEVICE_ENTER; | ||
144 | |||
145 | if (instance->rised <= 0) { | ||
146 | instance->rised = 0; | ||
147 | |||
148 | if (time_out) { | ||
149 | t = wait_event_interruptible_timeout(instance-> | ||
150 | wait_queue, | ||
151 | (instance->rised != | ||
152 | 0), t); | ||
153 | |||
154 | if (t == 0) { | ||
155 | PERROR | ||
156 | ("Wait on external interrupt timed out.\n"); | ||
157 | err = ME_ERRNO_TIMEOUT; | ||
158 | } | ||
159 | } else { | ||
160 | wait_event_interruptible(instance->wait_queue, | ||
161 | (instance->rised != 0)); | ||
162 | } | ||
163 | |||
164 | if (instance->rised < 0) { | ||
165 | PERROR("Wait on interrupt aborted by user.\n"); | ||
166 | err = ME_ERRNO_CANCELLED; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | if (signal_pending(current)) { | ||
171 | PERROR("Wait on external interrupt aborted by signal.\n"); | ||
172 | err = ME_ERRNO_SIGNAL; | ||
173 | } | ||
174 | |||
175 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
176 | instance->rised = 0; | ||
177 | *irq_count = instance->count; | ||
178 | *value = 0; | ||
179 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
180 | |||
181 | ME_SUBDEVICE_EXIT; | ||
182 | |||
183 | return err; | ||
184 | } | ||
185 | |||
186 | static int me8200_do_io_irq_stop(me_subdevice_t *subdevice, | ||
187 | struct file *filep, int channel, int flags) | ||
188 | { | ||
189 | me8200_do_subdevice_t *instance; | ||
190 | uint8_t tmp; | ||
191 | unsigned long cpu_flags; | ||
192 | |||
193 | PDEBUG("executed.\n"); | ||
194 | |||
195 | instance = (me8200_do_subdevice_t *) subdevice; | ||
196 | |||
197 | if (flags) { | ||
198 | PERROR("Invalid flag specified.\n"); | ||
199 | return ME_ERRNO_INVALID_FLAGS; | ||
200 | } | ||
201 | |||
202 | ME_SUBDEVICE_ENTER; | ||
203 | |||
204 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
205 | spin_lock(instance->irq_mode_lock); | ||
206 | tmp = inb(instance->irq_ctrl_reg); | ||
207 | tmp &= | ||
208 | ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER << | ||
209 | (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx)); | ||
210 | outb(tmp, instance->irq_ctrl_reg); | ||
211 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
212 | instance->irq_ctrl_reg - instance->reg_base, tmp); | ||
213 | spin_unlock(instance->irq_mode_lock); | ||
214 | instance->rised = -1; | ||
215 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
216 | wake_up_interruptible_all(&instance->wait_queue); | ||
217 | |||
218 | ME_SUBDEVICE_EXIT; | ||
219 | |||
220 | return ME_ERRNO_SUCCESS; | ||
221 | } | ||
222 | |||
223 | static int me8200_do_io_reset_subdevice(struct me_subdevice *subdevice, | ||
224 | struct file *filep, int flags) | ||
225 | { | ||
226 | me8200_do_subdevice_t *instance; | ||
227 | unsigned long cpu_flags; | ||
228 | uint8_t tmp; | ||
229 | |||
230 | PDEBUG("executed.\n"); | ||
231 | |||
232 | instance = (me8200_do_subdevice_t *) subdevice; | ||
233 | |||
234 | if (flags) { | ||
235 | PERROR("Invalid flag specified.\n"); | ||
236 | return ME_ERRNO_INVALID_FLAGS; | ||
237 | } | ||
238 | |||
239 | ME_SUBDEVICE_ENTER; | ||
240 | |||
241 | spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); | ||
242 | outb(0x00, instance->port_reg); | ||
243 | PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
244 | instance->port_reg - instance->reg_base, 0x00); | ||
245 | spin_lock(instance->irq_mode_lock); | ||
246 | tmp = inb(instance->irq_ctrl_reg); | ||
247 | tmp &= | ||
248 | ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER << | ||
249 | (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx)); | ||
250 | outb(tmp, instance->irq_ctrl_reg); | ||
251 | PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
252 | instance->irq_ctrl_reg - instance->reg_base, tmp); | ||
253 | spin_unlock(instance->irq_mode_lock); | ||
254 | instance->rised = -1; | ||
255 | instance->count = 0; | ||
256 | spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); | ||
257 | wake_up_interruptible_all(&instance->wait_queue); | ||
258 | |||
259 | ME_SUBDEVICE_EXIT; | ||
260 | |||
261 | return ME_ERRNO_SUCCESS; | ||
262 | } | ||
263 | |||
264 | static int me8200_do_io_single_config(me_subdevice_t *subdevice, | ||
265 | struct file *filep, | ||
266 | int channel, | ||
267 | int single_config, | ||
268 | int ref, | ||
269 | int trig_chan, | ||
270 | int trig_type, int trig_edge, int flags) | ||
271 | { | ||
272 | me8200_do_subdevice_t *instance; | ||
273 | int err = ME_ERRNO_SUCCESS; | ||
274 | unsigned long status; | ||
275 | |||
276 | PDEBUG("executed.\n"); | ||
277 | |||
278 | instance = (me8200_do_subdevice_t *) subdevice; | ||
279 | |||
280 | ME_SUBDEVICE_ENTER; | ||
281 | |||
282 | spin_lock_irqsave(&instance->subdevice_lock, status); | ||
283 | switch (flags) { | ||
284 | case ME_IO_SINGLE_CONFIG_NO_FLAGS: | ||
285 | case ME_IO_SINGLE_CONFIG_DIO_BYTE: | ||
286 | if (channel == 0) { | ||
287 | if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
288 | } else { | ||
289 | PERROR("Invalid byte direction specified.\n"); | ||
290 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
291 | } | ||
292 | } else { | ||
293 | PERROR("Invalid byte specified.\n"); | ||
294 | err = ME_ERRNO_INVALID_CHANNEL; | ||
295 | } | ||
296 | break; | ||
297 | |||
298 | default: | ||
299 | PERROR("Invalid flags specified.\n"); | ||
300 | err = ME_ERRNO_INVALID_FLAGS; | ||
301 | } | ||
302 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
303 | |||
304 | ME_SUBDEVICE_EXIT; | ||
305 | |||
306 | return err; | ||
307 | } | ||
308 | |||
309 | static int me8200_do_io_single_read(me_subdevice_t *subdevice, | ||
310 | struct file *filep, | ||
311 | int channel, | ||
312 | int *value, int time_out, int flags) | ||
313 | { | ||
314 | me8200_do_subdevice_t *instance; | ||
315 | int err = ME_ERRNO_SUCCESS; | ||
316 | unsigned long status; | ||
317 | |||
318 | PDEBUG("executed.\n"); | ||
319 | |||
320 | instance = (me8200_do_subdevice_t *) subdevice; | ||
321 | |||
322 | ME_SUBDEVICE_ENTER; | ||
323 | |||
324 | spin_lock_irqsave(&instance->subdevice_lock, status); | ||
325 | switch (flags) { | ||
326 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
327 | if ((channel >= 0) && (channel < 8)) { | ||
328 | *value = inb(instance->port_reg) & (0x1 << channel); | ||
329 | } else { | ||
330 | PERROR("Invalid bit number specified.\n"); | ||
331 | err = ME_ERRNO_INVALID_CHANNEL; | ||
332 | } | ||
333 | break; | ||
334 | |||
335 | case ME_IO_SINGLE_NO_FLAGS: | ||
336 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
337 | if (channel == 0) { | ||
338 | *value = inb(instance->port_reg); | ||
339 | } else { | ||
340 | PERROR("Invalid byte number specified.\n"); | ||
341 | err = ME_ERRNO_INVALID_CHANNEL; | ||
342 | } | ||
343 | break; | ||
344 | |||
345 | default: | ||
346 | PERROR("Invalid flags specified.\n"); | ||
347 | err = ME_ERRNO_INVALID_FLAGS; | ||
348 | } | ||
349 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
350 | |||
351 | ME_SUBDEVICE_EXIT; | ||
352 | |||
353 | return err; | ||
354 | } | ||
355 | |||
356 | static int me8200_do_io_single_write(me_subdevice_t *subdevice, | ||
357 | struct file *filep, | ||
358 | int channel, | ||
359 | int value, int time_out, int flags) | ||
360 | { | ||
361 | me8200_do_subdevice_t *instance; | ||
362 | int err = ME_ERRNO_SUCCESS; | ||
363 | uint8_t state; | ||
364 | unsigned long status; | ||
365 | |||
366 | PDEBUG("executed.\n"); | ||
367 | |||
368 | instance = (me8200_do_subdevice_t *) subdevice; | ||
369 | |||
370 | ME_SUBDEVICE_ENTER; | ||
371 | |||
372 | spin_lock_irqsave(&instance->subdevice_lock, status); | ||
373 | switch (flags) { | ||
374 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
375 | if ((channel >= 0) && (channel < 8)) { | ||
376 | state = inb(instance->port_reg); | ||
377 | state = | ||
378 | value ? (state | (0x1 << channel)) : (state & | ||
379 | ~(0x1 << | ||
380 | channel)); | ||
381 | outb(state, instance->port_reg); | ||
382 | PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
383 | instance->reg_base, | ||
384 | instance->port_reg - instance->reg_base, | ||
385 | state); | ||
386 | } else { | ||
387 | PERROR("Invalid bit number specified.\n"); | ||
388 | err = ME_ERRNO_INVALID_CHANNEL; | ||
389 | } | ||
390 | break; | ||
391 | |||
392 | case ME_IO_SINGLE_NO_FLAGS: | ||
393 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
394 | if (channel == 0) { | ||
395 | outb(value, instance->port_reg); | ||
396 | PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", | ||
397 | instance->reg_base, | ||
398 | instance->port_reg - instance->reg_base, | ||
399 | value); | ||
400 | } else { | ||
401 | PERROR("Invalid byte number specified.\n"); | ||
402 | err = ME_ERRNO_INVALID_CHANNEL; | ||
403 | } | ||
404 | break; | ||
405 | |||
406 | default: | ||
407 | PERROR("Invalid flags specified.\n"); | ||
408 | err = ME_ERRNO_INVALID_FLAGS; | ||
409 | } | ||
410 | spin_unlock_irqrestore(&instance->subdevice_lock, status); | ||
411 | |||
412 | ME_SUBDEVICE_EXIT; | ||
413 | |||
414 | return err; | ||
415 | } | ||
416 | |||
417 | static int me8200_do_query_number_channels(me_subdevice_t *subdevice, | ||
418 | int *number) | ||
419 | { | ||
420 | PDEBUG("executed.\n"); | ||
421 | *number = 8; | ||
422 | return ME_ERRNO_SUCCESS; | ||
423 | } | ||
424 | |||
425 | static int me8200_do_query_subdevice_type(me_subdevice_t *subdevice, | ||
426 | int *type, int *subtype) | ||
427 | { | ||
428 | PDEBUG("executed.\n"); | ||
429 | *type = ME_TYPE_DO; | ||
430 | *subtype = ME_SUBTYPE_SINGLE; | ||
431 | return ME_ERRNO_SUCCESS; | ||
432 | } | ||
433 | |||
434 | static int me8200_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) | ||
435 | { | ||
436 | PDEBUG("executed.\n"); | ||
437 | *caps = ME_CAPS_DIO_OVER_TEMP_IRQ; | ||
438 | return ME_ERRNO_SUCCESS; | ||
439 | } | ||
440 | |||
441 | static void me8200_do_destructor(struct me_subdevice *subdevice) | ||
442 | { | ||
443 | me8200_do_subdevice_t *instance; | ||
444 | |||
445 | PDEBUG("executed.\n"); | ||
446 | |||
447 | instance = (me8200_do_subdevice_t *) subdevice; | ||
448 | |||
449 | free_irq(instance->irq, (void *)instance); | ||
450 | me_subdevice_deinit(&instance->base); | ||
451 | kfree(instance); | ||
452 | } | ||
453 | |||
454 | static irqreturn_t me8200_do_isr(int irq, void *dev_id) | ||
455 | { | ||
456 | me8200_do_subdevice_t *instance; | ||
457 | uint16_t ctrl; | ||
458 | uint8_t irq_status; | ||
459 | |||
460 | instance = (me8200_do_subdevice_t *) dev_id; | ||
461 | |||
462 | if (irq != instance->irq) { | ||
463 | PERROR("Incorrect interrupt num: %d.\n", irq); | ||
464 | return IRQ_NONE; | ||
465 | } | ||
466 | |||
467 | irq_status = inb(instance->irq_status_reg); | ||
468 | if (! | ||
469 | (irq_status & | ||
470 | (ME8200_DO_IRQ_STATUS_BIT_ACTIVE << instance->do_idx))) { | ||
471 | PINFO | ||
472 | ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n", | ||
473 | jiffies, __func__, instance->do_idx, irq_status); | ||
474 | return IRQ_NONE; | ||
475 | } | ||
476 | |||
477 | PDEBUG("executed.\n"); | ||
478 | |||
479 | spin_lock(&instance->subdevice_lock); | ||
480 | instance->rised = 1; | ||
481 | instance->count++; | ||
482 | |||
483 | spin_lock(instance->irq_mode_lock); | ||
484 | ctrl = inw(instance->irq_ctrl_reg); | ||
485 | ctrl |= ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx; | ||
486 | outw(ctrl, instance->irq_ctrl_reg); | ||
487 | PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
488 | instance->irq_ctrl_reg - instance->reg_base, ctrl); | ||
489 | ctrl &= ~(ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx); | ||
490 | outw(ctrl, instance->irq_ctrl_reg); | ||
491 | PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, | ||
492 | instance->irq_ctrl_reg - instance->reg_base, ctrl); | ||
493 | spin_unlock(instance->irq_mode_lock); | ||
494 | spin_unlock(&instance->subdevice_lock); | ||
495 | wake_up_interruptible_all(&instance->wait_queue); | ||
496 | |||
497 | return IRQ_HANDLED; | ||
498 | } | ||
499 | |||
500 | me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base, | ||
501 | unsigned int do_idx, | ||
502 | int irq, | ||
503 | spinlock_t *irq_mode_lock) | ||
504 | { | ||
505 | me8200_do_subdevice_t *subdevice; | ||
506 | int err; | ||
507 | |||
508 | PDEBUG("executed.\n"); | ||
509 | |||
510 | /* Allocate memory for subdevice instance */ | ||
511 | subdevice = kmalloc(sizeof(me8200_do_subdevice_t), GFP_KERNEL); | ||
512 | |||
513 | if (!subdevice) { | ||
514 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
515 | return NULL; | ||
516 | } | ||
517 | |||
518 | memset(subdevice, 0, sizeof(me8200_do_subdevice_t)); | ||
519 | |||
520 | /* Initialize subdevice base class */ | ||
521 | err = me_subdevice_init(&subdevice->base); | ||
522 | |||
523 | if (err) { | ||
524 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
525 | kfree(subdevice); | ||
526 | return NULL; | ||
527 | } | ||
528 | // Initialize spin locks. | ||
529 | spin_lock_init(&subdevice->subdevice_lock); | ||
530 | |||
531 | subdevice->irq_mode_lock = irq_mode_lock; | ||
532 | |||
533 | /* Save the index of the digital output */ | ||
534 | subdevice->do_idx = do_idx; | ||
535 | subdevice->irq = irq; | ||
536 | |||
537 | /* Initialize the registers */ | ||
538 | if (do_idx == 0) { | ||
539 | subdevice->port_reg = reg_base + ME8200_DO_PORT_0_REG; | ||
540 | } else if (do_idx == 1) { | ||
541 | subdevice->port_reg = reg_base + ME8200_DO_PORT_1_REG; | ||
542 | } else { | ||
543 | PERROR("Wrong subdevice idx=%d.\n", do_idx); | ||
544 | kfree(subdevice); | ||
545 | return NULL; | ||
546 | } | ||
547 | subdevice->irq_ctrl_reg = reg_base + ME8200_IRQ_MODE_REG; | ||
548 | subdevice->irq_status_reg = reg_base + ME8200_DO_IRQ_STATUS_REG; | ||
549 | #ifdef MEDEBUG_DEBUG_REG | ||
550 | subdevice->reg_base = reg_base; | ||
551 | #endif | ||
552 | |||
553 | /* Initialize the wait queue */ | ||
554 | init_waitqueue_head(&subdevice->wait_queue); | ||
555 | |||
556 | /* Request the interrupt line */ | ||
557 | err = request_irq(irq, me8200_do_isr, | ||
558 | IRQF_DISABLED | IRQF_SHARED, | ||
559 | ME8200_NAME, (void *)subdevice); | ||
560 | |||
561 | if (err) { | ||
562 | PERROR("Cannot get interrupt line.\n"); | ||
563 | kfree(subdevice); | ||
564 | return NULL; | ||
565 | } | ||
566 | PINFO("Registered irq=%d.\n", irq); | ||
567 | |||
568 | /* Overload base class methods. */ | ||
569 | subdevice->base.me_subdevice_io_irq_start = me8200_do_io_irq_start; | ||
570 | subdevice->base.me_subdevice_io_irq_wait = me8200_do_io_irq_wait; | ||
571 | subdevice->base.me_subdevice_io_irq_stop = me8200_do_io_irq_stop; | ||
572 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
573 | me8200_do_io_reset_subdevice; | ||
574 | subdevice->base.me_subdevice_io_single_config = | ||
575 | me8200_do_io_single_config; | ||
576 | subdevice->base.me_subdevice_io_single_read = me8200_do_io_single_read; | ||
577 | subdevice->base.me_subdevice_io_single_write = | ||
578 | me8200_do_io_single_write; | ||
579 | subdevice->base.me_subdevice_query_number_channels = | ||
580 | me8200_do_query_number_channels; | ||
581 | subdevice->base.me_subdevice_query_subdevice_type = | ||
582 | me8200_do_query_subdevice_type; | ||
583 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
584 | me8200_do_query_subdevice_caps; | ||
585 | subdevice->base.me_subdevice_destructor = me8200_do_destructor; | ||
586 | |||
587 | subdevice->rised = 0; | ||
588 | subdevice->count = 0; | ||
589 | |||
590 | return subdevice; | ||
591 | } | ||
diff --git a/drivers/staging/meilhaus/me8200_do.h b/drivers/staging/meilhaus/me8200_do.h deleted file mode 100644 index 27581251c847..000000000000 --- a/drivers/staging/meilhaus/me8200_do.h +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_do.h | ||
3 | * | ||
4 | * @brief ME-8200 digital output subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_DO_H_ | ||
28 | #define _ME8200_DO_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The template subdevice class. | ||
36 | */ | ||
37 | typedef struct me8200_do_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *irq_mode_lock; | ||
44 | |||
45 | int irq; /**< The number of the interrupt request */ | ||
46 | int rised; /**< Flag to indicate if an interrupt occured */ | ||
47 | int count; /**< Counts the number of interrupts occured */ | ||
48 | wait_queue_head_t wait_queue; /**< To wait on interrupts */ | ||
49 | |||
50 | unsigned int do_idx; /**< The number of the digital output */ | ||
51 | |||
52 | unsigned long port_reg; /**< The digital output port */ | ||
53 | unsigned long irq_ctrl_reg; /**< The interrupt control register */ | ||
54 | unsigned long irq_status_reg; /**< The interrupt status register */ | ||
55 | #ifdef MEDEBUG_DEBUG_REG | ||
56 | unsigned long reg_base; | ||
57 | #endif | ||
58 | } me8200_do_subdevice_t; | ||
59 | |||
60 | /** | ||
61 | * @brief The constructor to generate a ME-8200 digital output subdevice instance. | ||
62 | * | ||
63 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
64 | * @param do_idx The index of the digital output subdevice on this device. | ||
65 | * | ||
66 | * @return Pointer to new instance on success.\n | ||
67 | * NULL on error. | ||
68 | */ | ||
69 | me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base, | ||
70 | unsigned int do_idx, | ||
71 | int irq, | ||
72 | spinlock_t * irq_mode_lock); | ||
73 | |||
74 | #endif | ||
75 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_do_reg.h b/drivers/staging/meilhaus/me8200_do_reg.h deleted file mode 100644 index 41095046037a..000000000000 --- a/drivers/staging/meilhaus/me8200_do_reg.h +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_ao_reg.h | ||
3 | * | ||
4 | * @brief ME-8200 analog output subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_DO_REG_H_ | ||
28 | #define _ME8200_DO_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME8200_DO_IRQ_STATUS_REG 0x0 // R | ||
33 | #define ME8200_DO_PORT_0_REG 0x1 // R/W | ||
34 | #define ME8200_DO_PORT_1_REG 0x2 // R/W | ||
35 | |||
36 | #define ME8200_DO_IRQ_STATUS_BIT_ACTIVE 0x1 | ||
37 | #define ME8200_DO_IRQ_STATUS_SHIFT 1 | ||
38 | |||
39 | #endif | ||
40 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8200_reg.h b/drivers/staging/meilhaus/me8200_reg.h deleted file mode 100644 index a73fe4d5b0ff..000000000000 --- a/drivers/staging/meilhaus/me8200_reg.h +++ /dev/null | |||
@@ -1,46 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8200_reg.h | ||
3 | * | ||
4 | * @brief ME-8200 register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8200_REG_H_ | ||
28 | #define _ME8200_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define ME8200_IRQ_MODE_REG 0xD // R/W | ||
33 | |||
34 | #define ME8200_IRQ_MODE_MASK 0x3 | ||
35 | |||
36 | #define ME8200_IRQ_MODE_MASK_MASK 0x0 | ||
37 | #define ME8200_IRQ_MODE_MASK_COMPARE 0x1 | ||
38 | |||
39 | #define ME8200_IRQ_MODE_BIT_ENABLE_POWER 0x10 | ||
40 | #define ME8200_IRQ_MODE_BIT_CLEAR_POWER 0x40 | ||
41 | |||
42 | #define ME8200_IRQ_MODE_DI_SHIFT 2 | ||
43 | #define ME8200_IRQ_MODE_POWER_SHIFT 1 | ||
44 | |||
45 | #endif | ||
46 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8254.c b/drivers/staging/meilhaus/me8254.c deleted file mode 100644 index d8f742a8ca99..000000000000 --- a/drivers/staging/meilhaus/me8254.c +++ /dev/null | |||
@@ -1,1176 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8254.c | ||
3 | * | ||
4 | * @brief 8254 subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef __KERNEL__ | ||
28 | # define __KERNEL__ | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Includes | ||
33 | */ | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/slab.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/io.h> | ||
39 | #include <linux/types.h> | ||
40 | |||
41 | #include "medefines.h" | ||
42 | #include "meinternal.h" | ||
43 | #include "meerror.h" | ||
44 | |||
45 | #include "medebug.h" | ||
46 | #include "me8254_reg.h" | ||
47 | #include "me8254.h" | ||
48 | |||
49 | /* | ||
50 | * Defines | ||
51 | */ | ||
52 | #define ME8254_NUMBER_CHANNELS 1 /**< One channel per counter. */ | ||
53 | #define ME8254_CTR_WIDTH 16 /**< One counter has 16 bits. */ | ||
54 | |||
55 | /* | ||
56 | * Functions | ||
57 | */ | ||
58 | |||
59 | static int me8254_io_reset_subdevice(struct me_subdevice *subdevice, | ||
60 | struct file *filep, int flags) | ||
61 | { | ||
62 | me8254_subdevice_t *instance; | ||
63 | uint8_t clk_src; | ||
64 | int err = ME_ERRNO_SUCCESS; | ||
65 | |||
66 | PDEBUG("executed.\n"); | ||
67 | |||
68 | instance = (me8254_subdevice_t *) subdevice; | ||
69 | |||
70 | if (flags) { | ||
71 | PERROR("Invalid flag specified.\n"); | ||
72 | return ME_ERRNO_INVALID_FLAGS; | ||
73 | } | ||
74 | |||
75 | ME_SUBDEVICE_ENTER; | ||
76 | |||
77 | spin_lock(&instance->subdevice_lock); | ||
78 | spin_lock(instance->ctrl_reg_lock); | ||
79 | if (instance->ctr_idx == 0) | ||
80 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 | | ||
81 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
82 | else if (instance->ctr_idx == 1) | ||
83 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 | | ||
84 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
85 | else | ||
86 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 | | ||
87 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
88 | spin_unlock(instance->ctrl_reg_lock); | ||
89 | |||
90 | outb(0x00, instance->val_reg); | ||
91 | outb(0x00, instance->val_reg); | ||
92 | |||
93 | spin_lock(instance->clk_src_reg_lock); | ||
94 | clk_src = inb(instance->clk_src_reg); | ||
95 | |||
96 | switch (instance->device_id) { | ||
97 | case PCI_DEVICE_ID_MEILHAUS_ME1400: | ||
98 | case PCI_DEVICE_ID_MEILHAUS_ME140A: | ||
99 | case PCI_DEVICE_ID_MEILHAUS_ME140B: | ||
100 | case PCI_DEVICE_ID_MEILHAUS_ME14E0: | ||
101 | case PCI_DEVICE_ID_MEILHAUS_ME14EA: | ||
102 | case PCI_DEVICE_ID_MEILHAUS_ME14EB: | ||
103 | if (instance->me8254_idx == 0) { | ||
104 | if (instance->ctr_idx == 0) | ||
105 | clk_src &= | ||
106 | ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ | | ||
107 | ME1400AB_8254_A_0_CLK_SRC_QUARZ); | ||
108 | else if (instance->ctr_idx == 1) | ||
109 | clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV); | ||
110 | else | ||
111 | clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV); | ||
112 | } else { | ||
113 | if (instance->ctr_idx == 0) | ||
114 | clk_src &= | ||
115 | ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ | | ||
116 | ME1400AB_8254_B_0_CLK_SRC_QUARZ); | ||
117 | else if (instance->ctr_idx == 1) | ||
118 | clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV); | ||
119 | else | ||
120 | clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV); | ||
121 | } | ||
122 | break; | ||
123 | |||
124 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
125 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
126 | switch (instance->me8254_idx) { | ||
127 | case 0: | ||
128 | case 2: | ||
129 | case 4: | ||
130 | case 6: | ||
131 | case 8: | ||
132 | if (instance->ctr_idx == 0) | ||
133 | clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); | ||
134 | else if (instance->ctr_idx == 1) | ||
135 | clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK); | ||
136 | else | ||
137 | clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK); | ||
138 | break; | ||
139 | |||
140 | default: | ||
141 | if (instance->ctr_idx == 0) | ||
142 | clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); | ||
143 | else if (instance->ctr_idx == 1) | ||
144 | clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK); | ||
145 | else | ||
146 | clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK); | ||
147 | break; | ||
148 | } | ||
149 | break; | ||
150 | |||
151 | case PCI_DEVICE_ID_MEILHAUS_ME4610: | ||
152 | case PCI_DEVICE_ID_MEILHAUS_ME4660: | ||
153 | case PCI_DEVICE_ID_MEILHAUS_ME4660I: | ||
154 | case PCI_DEVICE_ID_MEILHAUS_ME4660S: | ||
155 | case PCI_DEVICE_ID_MEILHAUS_ME4660IS: | ||
156 | case PCI_DEVICE_ID_MEILHAUS_ME4670: | ||
157 | case PCI_DEVICE_ID_MEILHAUS_ME4670I: | ||
158 | case PCI_DEVICE_ID_MEILHAUS_ME4670S: | ||
159 | case PCI_DEVICE_ID_MEILHAUS_ME4670IS: | ||
160 | case PCI_DEVICE_ID_MEILHAUS_ME4680: | ||
161 | case PCI_DEVICE_ID_MEILHAUS_ME4680I: | ||
162 | case PCI_DEVICE_ID_MEILHAUS_ME4680S: | ||
163 | case PCI_DEVICE_ID_MEILHAUS_ME4680IS: | ||
164 | case PCI_DEVICE_ID_MEILHAUS_ME8100_A: | ||
165 | case PCI_DEVICE_ID_MEILHAUS_ME8100_B: | ||
166 | |||
167 | /* No clock source register available */ | ||
168 | break; | ||
169 | |||
170 | default: | ||
171 | PERROR("Invalid device type.\n"); | ||
172 | err = ME_ERRNO_INTERNAL; | ||
173 | } | ||
174 | |||
175 | if (!err) | ||
176 | outb(clk_src, instance->clk_src_reg); | ||
177 | |||
178 | spin_unlock(instance->clk_src_reg_lock); | ||
179 | spin_unlock(&instance->subdevice_lock); | ||
180 | |||
181 | ME_SUBDEVICE_EXIT; | ||
182 | |||
183 | return err; | ||
184 | } | ||
185 | |||
186 | static int me1400_ab_ref_config(me8254_subdevice_t *instance, int ref) | ||
187 | { | ||
188 | uint8_t clk_src; | ||
189 | |||
190 | spin_lock(instance->clk_src_reg_lock); | ||
191 | clk_src = inb(instance->clk_src_reg); | ||
192 | |||
193 | switch (ref) { | ||
194 | case ME_REF_CTR_EXTERNAL: | ||
195 | if (instance->me8254_idx == 0) { | ||
196 | if (instance->ctr_idx == 0) | ||
197 | clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_QUARZ); | ||
198 | else if (instance->ctr_idx == 1) | ||
199 | clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV); | ||
200 | else | ||
201 | clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV); | ||
202 | } else { | ||
203 | if (instance->ctr_idx == 0) | ||
204 | clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_QUARZ); | ||
205 | else if (instance->ctr_idx == 1) | ||
206 | clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV); | ||
207 | else | ||
208 | clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV); | ||
209 | } | ||
210 | |||
211 | break; | ||
212 | |||
213 | case ME_REF_CTR_PREVIOUS: | ||
214 | if (instance->me8254_idx == 0) { | ||
215 | if (instance->ctr_idx == 0) { | ||
216 | PERROR("Invalid reference.\n"); | ||
217 | spin_unlock(instance->clk_src_reg_lock); | ||
218 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
219 | } else if (instance->ctr_idx == 1) | ||
220 | clk_src |= (ME1400AB_8254_A_1_CLK_SRC_PREV); | ||
221 | else | ||
222 | clk_src |= (ME1400AB_8254_A_2_CLK_SRC_PREV); | ||
223 | } else { | ||
224 | if (instance->ctr_idx == 0) { | ||
225 | PERROR("Invalid reference.\n"); | ||
226 | spin_unlock(instance->clk_src_reg_lock); | ||
227 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
228 | } else if (instance->ctr_idx == 1) | ||
229 | clk_src |= (ME1400AB_8254_B_1_CLK_SRC_PREV); | ||
230 | else | ||
231 | clk_src |= (ME1400AB_8254_B_2_CLK_SRC_PREV); | ||
232 | } | ||
233 | |||
234 | break; | ||
235 | |||
236 | case ME_REF_CTR_INTERNAL_1MHZ: | ||
237 | if (instance->me8254_idx == 0) { | ||
238 | if (instance->ctr_idx == 0) { | ||
239 | clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ); | ||
240 | clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ); | ||
241 | } else { | ||
242 | PERROR("Invalid reference.\n"); | ||
243 | spin_unlock(instance->clk_src_reg_lock); | ||
244 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
245 | } | ||
246 | } else { | ||
247 | if (instance->ctr_idx == 0) { | ||
248 | clk_src |= (ME1400AB_8254_B_0_CLK_SRC_QUARZ); | ||
249 | clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ); | ||
250 | } else { | ||
251 | PERROR("Invalid reference.\n"); | ||
252 | spin_unlock(instance->clk_src_reg_lock); | ||
253 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | break; | ||
258 | |||
259 | case ME_REF_CTR_INTERNAL_10MHZ: | ||
260 | if (instance->me8254_idx == 0) { | ||
261 | if (instance->ctr_idx == 0) { | ||
262 | clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ); | ||
263 | clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ); | ||
264 | } else { | ||
265 | PERROR("Invalid reference.\n"); | ||
266 | spin_unlock(instance->clk_src_reg_lock); | ||
267 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
268 | } | ||
269 | } else { | ||
270 | if (instance->ctr_idx == 0) { | ||
271 | clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ); | ||
272 | clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ); | ||
273 | } else { | ||
274 | PERROR("Invalid reference.\n"); | ||
275 | spin_unlock(instance->clk_src_reg_lock); | ||
276 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
277 | } | ||
278 | } | ||
279 | |||
280 | break; | ||
281 | |||
282 | default: | ||
283 | PERROR("Invalid reference.\n"); | ||
284 | spin_unlock(instance->clk_src_reg_lock); | ||
285 | return ME_ERRNO_INVALID_REF; | ||
286 | } | ||
287 | |||
288 | outb(clk_src, instance->clk_src_reg); | ||
289 | spin_unlock(instance->clk_src_reg_lock); | ||
290 | |||
291 | return ME_ERRNO_SUCCESS; | ||
292 | } | ||
293 | |||
294 | static int me1400_cd_ref_config(me8254_subdevice_t *instance, int ref) | ||
295 | { | ||
296 | uint8_t clk_src; | ||
297 | |||
298 | spin_lock(instance->clk_src_reg_lock); | ||
299 | clk_src = inb(instance->clk_src_reg); | ||
300 | |||
301 | switch (ref) { | ||
302 | case ME_REF_CTR_EXTERNAL: | ||
303 | switch (instance->me8254_idx) { | ||
304 | case 0: | ||
305 | case 2: | ||
306 | case 4: | ||
307 | case 6: | ||
308 | case 8: | ||
309 | if (instance->ctr_idx == 0) | ||
310 | clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); | ||
311 | else if (instance->ctr_idx == 1) | ||
312 | clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK); | ||
313 | else | ||
314 | clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK); | ||
315 | break; | ||
316 | |||
317 | default: | ||
318 | if (instance->ctr_idx == 0) | ||
319 | clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); | ||
320 | else if (instance->ctr_idx == 1) | ||
321 | clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK); | ||
322 | else | ||
323 | clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK); | ||
324 | break; | ||
325 | } | ||
326 | break; | ||
327 | |||
328 | case ME_REF_CTR_PREVIOUS: | ||
329 | switch (instance->me8254_idx) { | ||
330 | case 0: | ||
331 | case 2: | ||
332 | case 4: | ||
333 | case 6: | ||
334 | case 8: | ||
335 | if (instance->ctr_idx == 0) { | ||
336 | clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); | ||
337 | clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_PREV); | ||
338 | } else if (instance->ctr_idx == 1) { | ||
339 | clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK); | ||
340 | clk_src |= (ME1400CD_8254_ACE_1_CLK_SRC_PREV); | ||
341 | } else { | ||
342 | clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK); | ||
343 | clk_src |= (ME1400CD_8254_ACE_2_CLK_SRC_PREV); | ||
344 | } | ||
345 | break; | ||
346 | |||
347 | default: | ||
348 | if (instance->ctr_idx == 0) { | ||
349 | clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); | ||
350 | clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_PREV); | ||
351 | } else if (instance->ctr_idx == 1) { | ||
352 | clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK); | ||
353 | clk_src |= (ME1400CD_8254_BD_1_CLK_SRC_PREV); | ||
354 | } else { | ||
355 | clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK); | ||
356 | clk_src |= (ME1400CD_8254_BD_2_CLK_SRC_PREV); | ||
357 | } | ||
358 | break; | ||
359 | } | ||
360 | |||
361 | break; | ||
362 | |||
363 | case ME_REF_CTR_INTERNAL_1MHZ: | ||
364 | switch (instance->me8254_idx) { | ||
365 | case 0: | ||
366 | case 2: | ||
367 | case 4: | ||
368 | case 6: | ||
369 | case 8: | ||
370 | if (instance->ctr_idx == 0) { | ||
371 | clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); | ||
372 | clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_1MHZ); | ||
373 | } else { | ||
374 | PERROR("Invalid reference.\n"); | ||
375 | spin_unlock(instance->clk_src_reg_lock); | ||
376 | return ME_ERRNO_INVALID_REF; | ||
377 | } | ||
378 | |||
379 | break; | ||
380 | |||
381 | default: | ||
382 | if (instance->ctr_idx == 0) { | ||
383 | clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); | ||
384 | clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_1MHZ); | ||
385 | } else { | ||
386 | PERROR("Invalid reference.\n"); | ||
387 | spin_unlock(instance->clk_src_reg_lock); | ||
388 | return ME_ERRNO_INVALID_REF; | ||
389 | } | ||
390 | break; | ||
391 | } | ||
392 | |||
393 | break; | ||
394 | |||
395 | case ME_REF_CTR_INTERNAL_10MHZ: | ||
396 | switch (instance->me8254_idx) { | ||
397 | case 0: | ||
398 | case 2: | ||
399 | case 4: | ||
400 | case 6: | ||
401 | case 8: | ||
402 | if (instance->ctr_idx == 0) { | ||
403 | clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); | ||
404 | clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_10MHZ); | ||
405 | } else { | ||
406 | PERROR("Invalid reference.\n"); | ||
407 | spin_unlock(instance->clk_src_reg_lock); | ||
408 | return ME_ERRNO_INVALID_REF; | ||
409 | } | ||
410 | break; | ||
411 | |||
412 | default: | ||
413 | if (instance->ctr_idx == 0) { | ||
414 | clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); | ||
415 | clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_10MHZ); | ||
416 | } else { | ||
417 | PERROR("Invalid reference.\n"); | ||
418 | spin_unlock(instance->clk_src_reg_lock); | ||
419 | return ME_ERRNO_INVALID_REF; | ||
420 | } | ||
421 | |||
422 | break; | ||
423 | } | ||
424 | |||
425 | break; | ||
426 | |||
427 | default: | ||
428 | PERROR("Invalid reference.\n"); | ||
429 | spin_unlock(instance->clk_src_reg_lock); | ||
430 | return ME_ERRNO_INVALID_REF; | ||
431 | } | ||
432 | |||
433 | outb(clk_src, instance->clk_src_reg); | ||
434 | spin_unlock(instance->clk_src_reg_lock); | ||
435 | |||
436 | return ME_ERRNO_SUCCESS; | ||
437 | } | ||
438 | |||
439 | static int me4600_ref_config(me8254_subdevice_t *instance, int ref) | ||
440 | { | ||
441 | switch (ref) { | ||
442 | |||
443 | case ME_REF_CTR_EXTERNAL: | ||
444 | // Nothing to do | ||
445 | break; | ||
446 | |||
447 | default: | ||
448 | PERROR("Invalid reference.\n"); | ||
449 | // spin_unlock(instance->clk_src_reg_lock); | ||
450 | return ME_ERRNO_INVALID_REF; | ||
451 | } | ||
452 | |||
453 | return ME_ERRNO_SUCCESS; | ||
454 | } | ||
455 | |||
456 | static int me8100_ref_config(me8254_subdevice_t *instance, int ref) | ||
457 | { | ||
458 | switch (ref) { | ||
459 | |||
460 | case ME_REF_CTR_EXTERNAL: | ||
461 | // Nothing to do | ||
462 | break; | ||
463 | |||
464 | default: | ||
465 | PERROR("Invalid reference.\n"); | ||
466 | // spin_unlock(instance->clk_src_reg_lock); | ||
467 | return ME_ERRNO_INVALID_REF; | ||
468 | } | ||
469 | |||
470 | return ME_ERRNO_SUCCESS; | ||
471 | } | ||
472 | |||
473 | static int me8254_io_single_config(struct me_subdevice *subdevice, | ||
474 | struct file *filep, | ||
475 | int channel, | ||
476 | int single_config, | ||
477 | int ref, | ||
478 | int trig_chan, | ||
479 | int trig_type, int trig_edge, int flags) | ||
480 | { | ||
481 | me8254_subdevice_t *instance; | ||
482 | int err; | ||
483 | |||
484 | PDEBUG("executed.\n"); | ||
485 | |||
486 | if (channel) { | ||
487 | PERROR("Invalid channel.\n"); | ||
488 | return ME_ERRNO_INVALID_CHANNEL; | ||
489 | } | ||
490 | |||
491 | instance = (me8254_subdevice_t *) subdevice; | ||
492 | |||
493 | if (flags) { | ||
494 | PERROR("Invalid flag specified.\n"); | ||
495 | return ME_ERRNO_INVALID_FLAGS; | ||
496 | } | ||
497 | |||
498 | ME_SUBDEVICE_ENTER; | ||
499 | |||
500 | spin_lock(&instance->subdevice_lock); | ||
501 | // Configure the counter modes | ||
502 | if (instance->ctr_idx == 0) { | ||
503 | if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) { | ||
504 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 | | ||
505 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
506 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) { | ||
507 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M1 | | ||
508 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
509 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) { | ||
510 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M2 | | ||
511 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
512 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) { | ||
513 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M3 | | ||
514 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
515 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) { | ||
516 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M4 | | ||
517 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
518 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) { | ||
519 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M5 | | ||
520 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
521 | } else { | ||
522 | PERROR("Invalid single configuration.\n"); | ||
523 | spin_unlock(&instance->subdevice_lock); | ||
524 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
525 | } | ||
526 | } else if (instance->ctr_idx == 1) { | ||
527 | if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) { | ||
528 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 | | ||
529 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
530 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) { | ||
531 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M1 | | ||
532 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
533 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) { | ||
534 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M2 | | ||
535 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
536 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) { | ||
537 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M3 | | ||
538 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
539 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) { | ||
540 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M4 | | ||
541 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
542 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) { | ||
543 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M5 | | ||
544 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
545 | } else { | ||
546 | PERROR("Invalid single configuration.\n"); | ||
547 | spin_unlock(&instance->subdevice_lock); | ||
548 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
549 | } | ||
550 | } else { | ||
551 | if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) { | ||
552 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 | | ||
553 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
554 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) { | ||
555 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M1 | | ||
556 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
557 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) { | ||
558 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M2 | | ||
559 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
560 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) { | ||
561 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M3 | | ||
562 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
563 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) { | ||
564 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M4 | | ||
565 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
566 | } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) { | ||
567 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M5 | | ||
568 | ME8254_CTRL_BIN, instance->ctrl_reg); | ||
569 | } else { | ||
570 | PERROR("Invalid single configuration.\n"); | ||
571 | spin_unlock(&instance->subdevice_lock); | ||
572 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | switch (instance->device_id) { | ||
577 | case PCI_DEVICE_ID_MEILHAUS_ME1400: | ||
578 | case PCI_DEVICE_ID_MEILHAUS_ME14E0: | ||
579 | case PCI_DEVICE_ID_MEILHAUS_ME140A: | ||
580 | case PCI_DEVICE_ID_MEILHAUS_ME14EA: | ||
581 | case PCI_DEVICE_ID_MEILHAUS_ME140B: | ||
582 | case PCI_DEVICE_ID_MEILHAUS_ME14EB: | ||
583 | err = me1400_ab_ref_config(instance, ref); | ||
584 | |||
585 | if (err) { | ||
586 | spin_unlock(&instance->subdevice_lock); | ||
587 | return err; | ||
588 | } | ||
589 | |||
590 | break; | ||
591 | |||
592 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
593 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
594 | err = me1400_cd_ref_config(instance, ref); | ||
595 | |||
596 | if (err) { | ||
597 | spin_unlock(&instance->subdevice_lock); | ||
598 | return err; | ||
599 | } | ||
600 | |||
601 | break; | ||
602 | |||
603 | case PCI_DEVICE_ID_MEILHAUS_ME4610: | ||
604 | case PCI_DEVICE_ID_MEILHAUS_ME4660: | ||
605 | case PCI_DEVICE_ID_MEILHAUS_ME4660I: | ||
606 | case PCI_DEVICE_ID_MEILHAUS_ME4660S: | ||
607 | case PCI_DEVICE_ID_MEILHAUS_ME4660IS: | ||
608 | case PCI_DEVICE_ID_MEILHAUS_ME4670: | ||
609 | case PCI_DEVICE_ID_MEILHAUS_ME4670I: | ||
610 | case PCI_DEVICE_ID_MEILHAUS_ME4670S: | ||
611 | case PCI_DEVICE_ID_MEILHAUS_ME4670IS: | ||
612 | case PCI_DEVICE_ID_MEILHAUS_ME4680: | ||
613 | case PCI_DEVICE_ID_MEILHAUS_ME4680I: | ||
614 | case PCI_DEVICE_ID_MEILHAUS_ME4680S: | ||
615 | case PCI_DEVICE_ID_MEILHAUS_ME4680IS: | ||
616 | err = me4600_ref_config(instance, ref); | ||
617 | |||
618 | if (err) { | ||
619 | spin_unlock(&instance->subdevice_lock); | ||
620 | return err; | ||
621 | } | ||
622 | |||
623 | break; | ||
624 | |||
625 | case PCI_DEVICE_ID_MEILHAUS_ME8100_A: | ||
626 | case PCI_DEVICE_ID_MEILHAUS_ME8100_B: | ||
627 | err = me8100_ref_config(instance, ref); | ||
628 | |||
629 | if (err) { | ||
630 | spin_unlock(&instance->subdevice_lock); | ||
631 | return err; | ||
632 | } | ||
633 | |||
634 | break; | ||
635 | |||
636 | default: | ||
637 | PERROR("Invalid device type.\n"); | ||
638 | |||
639 | spin_unlock(&instance->subdevice_lock); | ||
640 | // spin_unlock(instance->clk_src_reg_lock); | ||
641 | return ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
642 | } | ||
643 | spin_unlock(&instance->subdevice_lock); | ||
644 | |||
645 | ME_SUBDEVICE_EXIT; | ||
646 | |||
647 | return ME_ERRNO_SUCCESS; | ||
648 | } | ||
649 | |||
650 | static int me8254_io_single_read(struct me_subdevice *subdevice, | ||
651 | struct file *filep, | ||
652 | int channel, | ||
653 | int *value, int time_out, int flags) | ||
654 | { | ||
655 | me8254_subdevice_t *instance; | ||
656 | uint16_t lo_byte; | ||
657 | uint16_t hi_byte; | ||
658 | |||
659 | PDEBUG("executed.\n"); | ||
660 | |||
661 | if (channel) { | ||
662 | PERROR("Invalid channel.\n"); | ||
663 | return ME_ERRNO_INVALID_CHANNEL; | ||
664 | } | ||
665 | |||
666 | instance = (me8254_subdevice_t *) subdevice; | ||
667 | |||
668 | if (flags) { | ||
669 | PERROR("Invalid flag specified.\n"); | ||
670 | return ME_ERRNO_INVALID_FLAGS; | ||
671 | } | ||
672 | |||
673 | ME_SUBDEVICE_ENTER; | ||
674 | |||
675 | spin_lock(&instance->subdevice_lock); | ||
676 | spin_lock(instance->ctrl_reg_lock); | ||
677 | if (instance->ctr_idx == 0) | ||
678 | outb(ME8254_CTRL_SC0 | ME8254_CTRL_TLO, instance->ctrl_reg); | ||
679 | else if (instance->ctr_idx == 1) | ||
680 | outb(ME8254_CTRL_SC1 | ME8254_CTRL_TLO, instance->ctrl_reg); | ||
681 | else | ||
682 | outb(ME8254_CTRL_SC2 | ME8254_CTRL_TLO, instance->ctrl_reg); | ||
683 | |||
684 | lo_byte = inb(instance->val_reg); | ||
685 | hi_byte = inb(instance->val_reg); | ||
686 | spin_unlock(instance->ctrl_reg_lock); | ||
687 | |||
688 | *value = lo_byte | (hi_byte << 8); | ||
689 | spin_unlock(&instance->subdevice_lock); | ||
690 | |||
691 | ME_SUBDEVICE_EXIT; | ||
692 | |||
693 | return ME_ERRNO_SUCCESS; | ||
694 | } | ||
695 | |||
696 | static int me8254_io_single_write(struct me_subdevice *subdevice, | ||
697 | struct file *filep, | ||
698 | int channel, | ||
699 | int value, int time_out, int flags) | ||
700 | { | ||
701 | me8254_subdevice_t *instance; | ||
702 | |||
703 | PDEBUG("executed.\n"); | ||
704 | |||
705 | if (channel) { | ||
706 | PERROR("Invalid channel.\n"); | ||
707 | return ME_ERRNO_INVALID_CHANNEL; | ||
708 | } | ||
709 | |||
710 | instance = (me8254_subdevice_t *) subdevice; | ||
711 | |||
712 | if (flags) { | ||
713 | PERROR("Invalid flag specified.\n"); | ||
714 | return ME_ERRNO_INVALID_FLAGS; | ||
715 | } | ||
716 | |||
717 | ME_SUBDEVICE_ENTER; | ||
718 | |||
719 | spin_lock(&instance->subdevice_lock); | ||
720 | outb(value, instance->val_reg); | ||
721 | outb((value >> 8), instance->val_reg); | ||
722 | spin_unlock(&instance->subdevice_lock); | ||
723 | |||
724 | ME_SUBDEVICE_EXIT; | ||
725 | |||
726 | return ME_ERRNO_SUCCESS; | ||
727 | } | ||
728 | |||
729 | static int me8254_query_number_channels(struct me_subdevice *subdevice, | ||
730 | int *number) | ||
731 | { | ||
732 | PDEBUG("executed.\n"); | ||
733 | *number = ME8254_NUMBER_CHANNELS; | ||
734 | return ME_ERRNO_SUCCESS; | ||
735 | } | ||
736 | |||
737 | static int me8254_query_subdevice_type(struct me_subdevice *subdevice, | ||
738 | int *type, int *subtype) | ||
739 | { | ||
740 | PDEBUG("executed.\n"); | ||
741 | *type = ME_TYPE_CTR; | ||
742 | *subtype = ME_SUBTYPE_CTR_8254; | ||
743 | return ME_ERRNO_SUCCESS; | ||
744 | } | ||
745 | |||
746 | static int me8254_query_subdevice_caps(struct me_subdevice *subdevice, | ||
747 | int *caps) | ||
748 | { | ||
749 | me8254_subdevice_t *instance; | ||
750 | PDEBUG("executed.\n"); | ||
751 | instance = (me8254_subdevice_t *) subdevice; | ||
752 | *caps = instance->caps; | ||
753 | return ME_ERRNO_SUCCESS; | ||
754 | } | ||
755 | |||
756 | static int me8254_query_subdevice_caps_args(struct me_subdevice *subdevice, | ||
757 | int cap, int *args, int count) | ||
758 | { | ||
759 | PDEBUG("executed.\n"); | ||
760 | |||
761 | if (count != 1) { | ||
762 | PERROR("Invalid capability argument count.\n"); | ||
763 | return ME_ERRNO_INVALID_CAP_ARG_COUNT; | ||
764 | } | ||
765 | |||
766 | if (cap == ME_CAP_CTR_WIDTH) { | ||
767 | args[0] = ME8254_CTR_WIDTH; | ||
768 | } else { | ||
769 | PERROR("Invalid capability.\n"); | ||
770 | return ME_ERRNO_INVALID_CAP; | ||
771 | } | ||
772 | |||
773 | return ME_ERRNO_SUCCESS; | ||
774 | } | ||
775 | |||
776 | static uint32_t me1400AB_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, | ||
777 | unsigned int ctr_idx) | ||
778 | { | ||
779 | switch (me8254_idx) { | ||
780 | |||
781 | case 0: | ||
782 | return (reg_base + ME1400AB_8254_A_0_VAL_REG + ctr_idx); | ||
783 | |||
784 | default: | ||
785 | return (reg_base + ME1400AB_8254_B_0_VAL_REG + ctr_idx); | ||
786 | } | ||
787 | |||
788 | return 0; | ||
789 | } | ||
790 | |||
791 | static uint32_t me1400AB_get_ctrl_reg(uint32_t reg_base, | ||
792 | unsigned int me8254_idx, | ||
793 | unsigned int ctr_idx) | ||
794 | { | ||
795 | switch (me8254_idx) { | ||
796 | case 0: | ||
797 | return (reg_base + ME1400AB_8254_A_CTRL_REG); | ||
798 | |||
799 | default: | ||
800 | return (reg_base + ME1400AB_8254_B_CTRL_REG); | ||
801 | } | ||
802 | |||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | static uint32_t me1400AB_get_clk_src_reg(uint32_t reg_base, | ||
807 | unsigned int me8254_idx, | ||
808 | unsigned int ctr_idx) | ||
809 | { | ||
810 | switch (me8254_idx) { | ||
811 | case 0: | ||
812 | return (reg_base + ME1400AB_CLK_SRC_REG); | ||
813 | |||
814 | default: | ||
815 | return (reg_base + ME1400AB_CLK_SRC_REG); | ||
816 | } | ||
817 | |||
818 | return 0; | ||
819 | } | ||
820 | |||
821 | static uint32_t me1400CD_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, | ||
822 | unsigned int ctr_idx) | ||
823 | { | ||
824 | switch (me8254_idx) { | ||
825 | case 0: | ||
826 | return (reg_base + ME1400C_8254_A_0_VAL_REG + ctr_idx); | ||
827 | |||
828 | case 1: | ||
829 | return (reg_base + ME1400C_8254_B_0_VAL_REG + ctr_idx); | ||
830 | |||
831 | case 2: | ||
832 | return (reg_base + ME1400C_8254_C_0_VAL_REG + ctr_idx); | ||
833 | |||
834 | case 3: | ||
835 | return (reg_base + ME1400C_8254_D_0_VAL_REG + ctr_idx); | ||
836 | |||
837 | case 4: | ||
838 | return (reg_base + ME1400C_8254_E_0_VAL_REG + ctr_idx); | ||
839 | |||
840 | case 5: | ||
841 | return (reg_base + ME1400D_8254_A_0_VAL_REG + ctr_idx); | ||
842 | |||
843 | case 6: | ||
844 | return (reg_base + ME1400D_8254_B_0_VAL_REG + ctr_idx); | ||
845 | |||
846 | case 7: | ||
847 | return (reg_base + ME1400D_8254_C_0_VAL_REG + ctr_idx); | ||
848 | |||
849 | case 8: | ||
850 | return (reg_base + ME1400D_8254_D_0_VAL_REG + ctr_idx); | ||
851 | |||
852 | default: | ||
853 | return (reg_base + ME1400D_8254_E_0_VAL_REG + ctr_idx); | ||
854 | } | ||
855 | |||
856 | return 0; | ||
857 | } | ||
858 | |||
859 | static uint32_t me1400CD_get_ctrl_reg(uint32_t reg_base, | ||
860 | unsigned int me8254_idx, | ||
861 | unsigned int ctr_idx) | ||
862 | { | ||
863 | switch (me8254_idx) { | ||
864 | case 0: | ||
865 | return (reg_base + ME1400C_8254_A_CTRL_REG); | ||
866 | |||
867 | case 1: | ||
868 | return (reg_base + ME1400C_8254_B_CTRL_REG); | ||
869 | |||
870 | case 2: | ||
871 | return (reg_base + ME1400C_8254_C_CTRL_REG); | ||
872 | |||
873 | case 3: | ||
874 | return (reg_base + ME1400C_8254_D_CTRL_REG); | ||
875 | |||
876 | case 4: | ||
877 | return (reg_base + ME1400C_8254_E_CTRL_REG); | ||
878 | |||
879 | case 5: | ||
880 | return (reg_base + ME1400D_8254_A_CTRL_REG); | ||
881 | |||
882 | case 6: | ||
883 | return (reg_base + ME1400D_8254_B_CTRL_REG); | ||
884 | |||
885 | case 7: | ||
886 | return (reg_base + ME1400D_8254_C_CTRL_REG); | ||
887 | |||
888 | case 8: | ||
889 | return (reg_base + ME1400D_8254_D_CTRL_REG); | ||
890 | |||
891 | default: | ||
892 | return (reg_base + ME1400D_8254_E_CTRL_REG); | ||
893 | } | ||
894 | |||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | static uint32_t me1400CD_get_clk_src_reg(uint32_t reg_base, | ||
899 | unsigned int me8254_idx, | ||
900 | unsigned int ctr_idx) | ||
901 | { | ||
902 | switch (me8254_idx) { | ||
903 | case 0: | ||
904 | return (reg_base + ME1400C_CLK_SRC_0_REG); | ||
905 | |||
906 | case 1: | ||
907 | return (reg_base + ME1400C_CLK_SRC_0_REG); | ||
908 | |||
909 | case 2: | ||
910 | return (reg_base + ME1400C_CLK_SRC_1_REG); | ||
911 | |||
912 | case 3: | ||
913 | return (reg_base + ME1400C_CLK_SRC_1_REG); | ||
914 | |||
915 | case 4: | ||
916 | return (reg_base + ME1400C_CLK_SRC_2_REG); | ||
917 | |||
918 | case 5: | ||
919 | return (reg_base + ME1400D_CLK_SRC_0_REG); | ||
920 | |||
921 | case 6: | ||
922 | return (reg_base + ME1400D_CLK_SRC_0_REG); | ||
923 | |||
924 | case 7: | ||
925 | return (reg_base + ME1400D_CLK_SRC_1_REG); | ||
926 | |||
927 | case 8: | ||
928 | return (reg_base + ME1400D_CLK_SRC_1_REG); | ||
929 | |||
930 | default: | ||
931 | return (reg_base + ME1400D_CLK_SRC_2_REG); | ||
932 | } | ||
933 | |||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | static uint32_t me4600_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, | ||
938 | unsigned int ctr_idx) | ||
939 | { | ||
940 | return (reg_base + ME4600_8254_0_VAL_REG + ctr_idx); | ||
941 | } | ||
942 | |||
943 | static uint32_t me4600_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx, | ||
944 | unsigned int ctr_idx) | ||
945 | { | ||
946 | return (reg_base + ME4600_8254_CTRL_REG); | ||
947 | } | ||
948 | |||
949 | static uint32_t me8100_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, | ||
950 | unsigned int ctr_idx) | ||
951 | { | ||
952 | return (reg_base + ME8100_COUNTER_REG_0 + ctr_idx * 2); | ||
953 | } | ||
954 | |||
955 | static uint32_t me8100_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx, | ||
956 | unsigned int ctr_idx) | ||
957 | { | ||
958 | return (reg_base + ME8100_COUNTER_CTRL_REG); | ||
959 | } | ||
960 | |||
961 | me8254_subdevice_t *me8254_constructor(uint32_t device_id, | ||
962 | uint32_t reg_base, | ||
963 | unsigned int me8254_idx, | ||
964 | unsigned int ctr_idx, | ||
965 | spinlock_t *ctrl_reg_lock, | ||
966 | spinlock_t *clk_src_reg_lock) | ||
967 | { | ||
968 | me8254_subdevice_t *subdevice; | ||
969 | int err; | ||
970 | |||
971 | PDEBUG("executed.\n"); | ||
972 | |||
973 | // Allocate memory for subdevice instance | ||
974 | subdevice = kmalloc(sizeof(me8254_subdevice_t), GFP_KERNEL); | ||
975 | |||
976 | if (!subdevice) { | ||
977 | PERROR("Cannot get memory for 8254 instance.\n"); | ||
978 | return NULL; | ||
979 | } | ||
980 | |||
981 | memset(subdevice, 0, sizeof(me8254_subdevice_t)); | ||
982 | |||
983 | // Check if counter index is out of range | ||
984 | |||
985 | if (ctr_idx > 2) { | ||
986 | PERROR("Counter index is out of range.\n"); | ||
987 | kfree(subdevice); | ||
988 | return NULL; | ||
989 | } | ||
990 | // Initialize subdevice base class | ||
991 | err = me_subdevice_init(&subdevice->base); | ||
992 | |||
993 | if (err) { | ||
994 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
995 | kfree(subdevice); | ||
996 | return NULL; | ||
997 | } | ||
998 | // Initialize spin locks. | ||
999 | spin_lock_init(&subdevice->subdevice_lock); | ||
1000 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
1001 | subdevice->clk_src_reg_lock = clk_src_reg_lock; | ||
1002 | |||
1003 | // Save type of Meilhaus device | ||
1004 | subdevice->device_id = device_id; | ||
1005 | |||
1006 | // Save the indices | ||
1007 | subdevice->me8254_idx = me8254_idx; | ||
1008 | subdevice->ctr_idx = ctr_idx; | ||
1009 | |||
1010 | // Do device specific initialization | ||
1011 | switch (device_id) { | ||
1012 | |||
1013 | case PCI_DEVICE_ID_MEILHAUS_ME140A: | ||
1014 | case PCI_DEVICE_ID_MEILHAUS_ME14EA: | ||
1015 | // Check if 8254 index is out of range | ||
1016 | if (me8254_idx > 0) { | ||
1017 | PERROR("8254 index is out of range.\n"); | ||
1018 | me_subdevice_deinit(&subdevice->base); | ||
1019 | kfree(subdevice); | ||
1020 | return NULL; | ||
1021 | } | ||
1022 | |||
1023 | case PCI_DEVICE_ID_MEILHAUS_ME140B: // Fall through | ||
1024 | case PCI_DEVICE_ID_MEILHAUS_ME14EB: | ||
1025 | // Check if 8254 index is out of range | ||
1026 | if (me8254_idx > 1) { | ||
1027 | PERROR("8254 index is out of range.\n"); | ||
1028 | me_subdevice_deinit(&subdevice->base); | ||
1029 | kfree(subdevice); | ||
1030 | return NULL; | ||
1031 | } | ||
1032 | // Initialize the counters capabilities | ||
1033 | if (ctr_idx == 0) | ||
1034 | subdevice->caps = | ||
1035 | ME_CAPS_CTR_CLK_INTERNAL_1MHZ | | ||
1036 | ME_CAPS_CTR_CLK_INTERNAL_10MHZ | | ||
1037 | ME_CAPS_CTR_CLK_EXTERNAL; | ||
1038 | else | ||
1039 | subdevice->caps = | ||
1040 | ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL; | ||
1041 | |||
1042 | // Get the counters registers | ||
1043 | subdevice->val_reg = | ||
1044 | me1400AB_get_val_reg(reg_base, me8254_idx, ctr_idx); | ||
1045 | subdevice->ctrl_reg = | ||
1046 | me1400AB_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); | ||
1047 | subdevice->clk_src_reg = | ||
1048 | me1400AB_get_clk_src_reg(reg_base, me8254_idx, ctr_idx); | ||
1049 | break; | ||
1050 | |||
1051 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
1052 | // Check if 8254 index is out of range | ||
1053 | if (me8254_idx > 4) { | ||
1054 | PERROR("8254 index is out of range.\n"); | ||
1055 | me_subdevice_deinit(&subdevice->base); | ||
1056 | kfree(subdevice); | ||
1057 | return NULL; | ||
1058 | } | ||
1059 | |||
1060 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
1061 | // Check if 8254 index is out of range | ||
1062 | if (me8254_idx > 9) { | ||
1063 | PERROR("8254 index is out of range.\n"); | ||
1064 | me_subdevice_deinit(&subdevice->base); | ||
1065 | kfree(subdevice); | ||
1066 | return NULL; | ||
1067 | } | ||
1068 | // Initialize the counters capabilities | ||
1069 | if (ctr_idx == 0) { | ||
1070 | if (me8254_idx == 0) | ||
1071 | subdevice->caps = | ||
1072 | ME_CAPS_CTR_CLK_PREVIOUS | | ||
1073 | ME_CAPS_CTR_CLK_INTERNAL_1MHZ | | ||
1074 | ME_CAPS_CTR_CLK_INTERNAL_10MHZ | | ||
1075 | ME_CAPS_CTR_CLK_EXTERNAL; | ||
1076 | else | ||
1077 | subdevice->caps = | ||
1078 | ME_CAPS_CTR_CLK_INTERNAL_1MHZ | | ||
1079 | ME_CAPS_CTR_CLK_INTERNAL_10MHZ | | ||
1080 | ME_CAPS_CTR_CLK_EXTERNAL; | ||
1081 | } else | ||
1082 | subdevice->caps = | ||
1083 | ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL; | ||
1084 | |||
1085 | // Get the counters registers | ||
1086 | subdevice->val_reg = | ||
1087 | me1400CD_get_val_reg(reg_base, me8254_idx, ctr_idx); | ||
1088 | subdevice->ctrl_reg = | ||
1089 | me1400CD_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); | ||
1090 | subdevice->clk_src_reg = | ||
1091 | me1400CD_get_clk_src_reg(reg_base, me8254_idx, ctr_idx); | ||
1092 | break; | ||
1093 | |||
1094 | case PCI_DEVICE_ID_MEILHAUS_ME4610: | ||
1095 | case PCI_DEVICE_ID_MEILHAUS_ME4660: | ||
1096 | case PCI_DEVICE_ID_MEILHAUS_ME4660I: | ||
1097 | case PCI_DEVICE_ID_MEILHAUS_ME4660S: | ||
1098 | case PCI_DEVICE_ID_MEILHAUS_ME4660IS: | ||
1099 | case PCI_DEVICE_ID_MEILHAUS_ME4670: | ||
1100 | case PCI_DEVICE_ID_MEILHAUS_ME4670I: | ||
1101 | case PCI_DEVICE_ID_MEILHAUS_ME4670S: | ||
1102 | case PCI_DEVICE_ID_MEILHAUS_ME4670IS: | ||
1103 | case PCI_DEVICE_ID_MEILHAUS_ME4680: | ||
1104 | case PCI_DEVICE_ID_MEILHAUS_ME4680I: | ||
1105 | case PCI_DEVICE_ID_MEILHAUS_ME4680S: | ||
1106 | case PCI_DEVICE_ID_MEILHAUS_ME4680IS: | ||
1107 | // Check if 8254 index is out of range | ||
1108 | if (me8254_idx > 0) { | ||
1109 | PERROR("8254 index is out of range.\n"); | ||
1110 | me_subdevice_deinit(&subdevice->base); | ||
1111 | kfree(subdevice); | ||
1112 | return NULL; | ||
1113 | } | ||
1114 | // Initialize the counters capabilities | ||
1115 | subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL; | ||
1116 | |||
1117 | // Get the counters registers | ||
1118 | subdevice->val_reg = | ||
1119 | me4600_get_val_reg(reg_base, me8254_idx, ctr_idx); | ||
1120 | subdevice->ctrl_reg = | ||
1121 | me4600_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); | ||
1122 | subdevice->clk_src_reg = 0; // Not used | ||
1123 | break; | ||
1124 | |||
1125 | case PCI_DEVICE_ID_MEILHAUS_ME8100_A: | ||
1126 | case PCI_DEVICE_ID_MEILHAUS_ME8100_B: | ||
1127 | // Check if 8254 index is out of range | ||
1128 | if (me8254_idx > 0) { | ||
1129 | PERROR("8254 index is out of range.\n"); | ||
1130 | me_subdevice_deinit(&subdevice->base); | ||
1131 | kfree(subdevice); | ||
1132 | return NULL; | ||
1133 | } | ||
1134 | // Initialize the counters capabilities | ||
1135 | subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL; | ||
1136 | |||
1137 | // Get the counters registers | ||
1138 | subdevice->val_reg = | ||
1139 | me8100_get_val_reg(reg_base, me8254_idx, ctr_idx); | ||
1140 | subdevice->ctrl_reg = | ||
1141 | me8100_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); | ||
1142 | subdevice->clk_src_reg = 0; // Not used | ||
1143 | break; | ||
1144 | |||
1145 | case PCI_DEVICE_ID_MEILHAUS_ME4650: | ||
1146 | case PCI_DEVICE_ID_MEILHAUS_ME1400: | ||
1147 | case PCI_DEVICE_ID_MEILHAUS_ME14E0: | ||
1148 | PERROR("No 8254 subdevices available for subdevice device.\n"); | ||
1149 | me_subdevice_deinit(&subdevice->base); | ||
1150 | kfree(subdevice); | ||
1151 | return NULL; | ||
1152 | |||
1153 | default: | ||
1154 | PERROR("Unknown device type.\n"); | ||
1155 | me_subdevice_deinit(&subdevice->base); | ||
1156 | kfree(subdevice); | ||
1157 | return NULL; | ||
1158 | } | ||
1159 | |||
1160 | // Overload subdevice base class methods. | ||
1161 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
1162 | me8254_io_reset_subdevice; | ||
1163 | subdevice->base.me_subdevice_io_single_config = me8254_io_single_config; | ||
1164 | subdevice->base.me_subdevice_io_single_read = me8254_io_single_read; | ||
1165 | subdevice->base.me_subdevice_io_single_write = me8254_io_single_write; | ||
1166 | subdevice->base.me_subdevice_query_number_channels = | ||
1167 | me8254_query_number_channels; | ||
1168 | subdevice->base.me_subdevice_query_subdevice_type = | ||
1169 | me8254_query_subdevice_type; | ||
1170 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
1171 | me8254_query_subdevice_caps; | ||
1172 | subdevice->base.me_subdevice_query_subdevice_caps_args = | ||
1173 | me8254_query_subdevice_caps_args; | ||
1174 | |||
1175 | return subdevice; | ||
1176 | } | ||
diff --git a/drivers/staging/meilhaus/me8254.h b/drivers/staging/meilhaus/me8254.h deleted file mode 100644 index 572b7196d5a8..000000000000 --- a/drivers/staging/meilhaus/me8254.h +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8254.h | ||
3 | * | ||
4 | * @brief 8254 counter implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _ME8254_H_ | ||
28 | #define _ME8254_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | #include "meslock.h" | ||
32 | |||
33 | #ifdef __KERNEL__ | ||
34 | |||
35 | /** | ||
36 | * @brief The 8254 subdevice class. | ||
37 | */ | ||
38 | typedef struct me8254_subdevice { | ||
39 | /* Inheritance */ | ||
40 | me_subdevice_t base; /**< The subdevice base class. */ | ||
41 | |||
42 | /* Attributes */ | ||
43 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
44 | |||
45 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect the control register from concurrent access. */ | ||
46 | spinlock_t *clk_src_reg_lock; /**< Spin lock to protect the clock source register from concurrent access. */ | ||
47 | |||
48 | uint32_t device_id; /**< The Meilhaus device type carrying the 8254 chip. */ | ||
49 | int me8254_idx; /**< The index of the 8254 chip on the device. */ | ||
50 | int ctr_idx; /**< The index of the counter on the 8254 chip. */ | ||
51 | |||
52 | int caps; /**< Holds the device capabilities. */ | ||
53 | |||
54 | unsigned long val_reg; /**< Holds the actual counter value. */ | ||
55 | unsigned long ctrl_reg; /**< Register to configure the 8254 modes. */ | ||
56 | unsigned long clk_src_reg; /**< Register to configure the counter connections. */ | ||
57 | } me8254_subdevice_t; | ||
58 | |||
59 | /** | ||
60 | * @brief The constructor to generate a 8254 instance. | ||
61 | * | ||
62 | * @param device_id The kind of Meilhaus device holding the 8254. | ||
63 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
64 | * @param me8254_idx The index of the 8254 chip on the Meilhaus device. | ||
65 | * @param ctr_idx The index of the counter inside a 8254 chip. | ||
66 | * @param ctrl_reg_lock Pointer to spin lock protecting the 8254 control register from concurrent access. | ||
67 | * @param clk_src_reg_lock Pointer to spin lock protecting the clock source register from concurrent access. | ||
68 | * | ||
69 | * @return Pointer to new instance on success.\n | ||
70 | * NULL on error. | ||
71 | */ | ||
72 | me8254_subdevice_t *me8254_constructor(uint32_t device_id, | ||
73 | uint32_t reg_base, | ||
74 | unsigned int me8254_idx, | ||
75 | unsigned int ctr_idx, | ||
76 | spinlock_t * ctrl_reg_lock, | ||
77 | spinlock_t * clk_src_reg_lock); | ||
78 | |||
79 | #endif | ||
80 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8254_reg.h b/drivers/staging/meilhaus/me8254_reg.h deleted file mode 100644 index 7e2c36b46f56..000000000000 --- a/drivers/staging/meilhaus/me8254_reg.h +++ /dev/null | |||
@@ -1,172 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8254_reg.h | ||
3 | * | ||
4 | * @brief 8254 counter register definitions. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME8254_REG_H_ | ||
10 | #define _ME8254_REG_H_ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | |||
14 | /* ME1400 A/B register offsets */ | ||
15 | #define ME1400AB_8254_A_0_VAL_REG 0x0004 /**< Offset of 8254 A counter 0 value register. */ | ||
16 | #define ME1400AB_8254_A_1_VAL_REG 0x0005 /**< Offset of 8254 A counter 1 value register. */ | ||
17 | #define ME1400AB_8254_A_2_VAL_REG 0x0006 /**< Offset of 8254 A counter 2 value register. */ | ||
18 | #define ME1400AB_8254_A_CTRL_REG 0x0007 /**< Offset of 8254 A control register. */ | ||
19 | |||
20 | #define ME1400AB_8254_B_0_VAL_REG 0x000C /**< Offset of 8254 B counter 0 value register. */ | ||
21 | #define ME1400AB_8254_B_1_VAL_REG 0x000D /**< Offset of 8254 B counter 1 value register. */ | ||
22 | #define ME1400AB_8254_B_2_VAL_REG 0x000E /**< Offset of 8254 B counter 2 value register. */ | ||
23 | #define ME1400AB_8254_B_CTRL_REG 0x000F /**< Offset of 8254 B control register. */ | ||
24 | |||
25 | #define ME1400AB_CLK_SRC_REG 0x0010 /**< Offset of clock source register. */ | ||
26 | |||
27 | /* ME1400 C register offsets */ | ||
28 | #define ME1400C_8254_A_0_VAL_REG 0x0004 /**< Offset of 8254 A counter 0 value register. */ | ||
29 | #define ME1400C_8254_A_1_VAL_REG 0x0005 /**< Offset of 8254 A counter 0 value register. */ | ||
30 | #define ME1400C_8254_A_2_VAL_REG 0x0006 /**< Offset of 8254 A counter 0 value register. */ | ||
31 | #define ME1400C_8254_A_CTRL_REG 0x0007 /**< Offset of 8254 A control register. */ | ||
32 | |||
33 | #define ME1400C_8254_B_0_VAL_REG 0x000C /**< Offset of 8254 B counter 0 value register. */ | ||
34 | #define ME1400C_8254_B_1_VAL_REG 0x000D /**< Offset of 8254 B counter 0 value register. */ | ||
35 | #define ME1400C_8254_B_2_VAL_REG 0x000E /**< Offset of 8254 B counter 0 value register. */ | ||
36 | #define ME1400C_8254_B_CTRL_REG 0x000F /**< Offset of 8254 B control register. */ | ||
37 | |||
38 | #define ME1400C_8254_C_0_VAL_REG 0x0010 /**< Offset of 8254 C counter 0 value register. */ | ||
39 | #define ME1400C_8254_C_1_VAL_REG 0x0011 /**< Offset of 8254 C counter 0 value register. */ | ||
40 | #define ME1400C_8254_C_2_VAL_REG 0x0012 /**< Offset of 8254 C counter 0 value register. */ | ||
41 | #define ME1400C_8254_C_CTRL_REG 0x0013 /**< Offset of 8254 C control register. */ | ||
42 | |||
43 | #define ME1400C_8254_D_0_VAL_REG 0x0014 /**< Offset of 8254 D counter 0 value register. */ | ||
44 | #define ME1400C_8254_D_1_VAL_REG 0x0015 /**< Offset of 8254 D counter 0 value register. */ | ||
45 | #define ME1400C_8254_D_2_VAL_REG 0x0016 /**< Offset of 8254 D counter 0 value register. */ | ||
46 | #define ME1400C_8254_D_CTRL_REG 0x0017 /**< Offset of 8254 D control register. */ | ||
47 | |||
48 | #define ME1400C_8254_E_0_VAL_REG 0x0018 /**< Offset of 8254 E counter 0 value register. */ | ||
49 | #define ME1400C_8254_E_1_VAL_REG 0x0019 /**< Offset of 8254 E counter 0 value register. */ | ||
50 | #define ME1400C_8254_E_2_VAL_REG 0x001A /**< Offset of 8254 E counter 0 value register. */ | ||
51 | #define ME1400C_8254_E_CTRL_REG 0x001B /**< Offset of 8254 E control register. */ | ||
52 | |||
53 | #define ME1400C_CLK_SRC_0_REG 0x001C /**< Offset of clock source register 0. */ | ||
54 | #define ME1400C_CLK_SRC_1_REG 0x001D /**< Offset of clock source register 1. */ | ||
55 | #define ME1400C_CLK_SRC_2_REG 0x001E /**< Offset of clock source register 2. */ | ||
56 | |||
57 | /* ME1400 D register offsets */ | ||
58 | #define ME1400D_8254_A_0_VAL_REG 0x0044 /**< Offset of 8254 A counter 0 value register. */ | ||
59 | #define ME1400D_8254_A_1_VAL_REG 0x0045 /**< Offset of 8254 A counter 0 value register. */ | ||
60 | #define ME1400D_8254_A_2_VAL_REG 0x0046 /**< Offset of 8254 A counter 0 value register. */ | ||
61 | #define ME1400D_8254_A_CTRL_REG 0x0047 /**< Offset of 8254 A control register. */ | ||
62 | |||
63 | #define ME1400D_8254_B_0_VAL_REG 0x004C /**< Offset of 8254 B counter 0 value register. */ | ||
64 | #define ME1400D_8254_B_1_VAL_REG 0x004D /**< Offset of 8254 B counter 0 value register. */ | ||
65 | #define ME1400D_8254_B_2_VAL_REG 0x004E /**< Offset of 8254 B counter 0 value register. */ | ||
66 | #define ME1400D_8254_B_CTRL_REG 0x004F /**< Offset of 8254 B control register. */ | ||
67 | |||
68 | #define ME1400D_8254_C_0_VAL_REG 0x0050 /**< Offset of 8254 C counter 0 value register. */ | ||
69 | #define ME1400D_8254_C_1_VAL_REG 0x0051 /**< Offset of 8254 C counter 0 value register. */ | ||
70 | #define ME1400D_8254_C_2_VAL_REG 0x0052 /**< Offset of 8254 C counter 0 value register. */ | ||
71 | #define ME1400D_8254_C_CTRL_REG 0x0053 /**< Offset of 8254 C control register. */ | ||
72 | |||
73 | #define ME1400D_8254_D_0_VAL_REG 0x0054 /**< Offset of 8254 D counter 0 value register. */ | ||
74 | #define ME1400D_8254_D_1_VAL_REG 0x0055 /**< Offset of 8254 D counter 0 value register. */ | ||
75 | #define ME1400D_8254_D_2_VAL_REG 0x0056 /**< Offset of 8254 D counter 0 value register. */ | ||
76 | #define ME1400D_8254_D_CTRL_REG 0x0057 /**< Offset of 8254 D control register. */ | ||
77 | |||
78 | #define ME1400D_8254_E_0_VAL_REG 0x0058 /**< Offset of 8254 E counter 0 value register. */ | ||
79 | #define ME1400D_8254_E_1_VAL_REG 0x0059 /**< Offset of 8254 E counter 0 value register. */ | ||
80 | #define ME1400D_8254_E_2_VAL_REG 0x005A /**< Offset of 8254 E counter 0 value register. */ | ||
81 | #define ME1400D_8254_E_CTRL_REG 0x005B /**< Offset of 8254 E control register. */ | ||
82 | |||
83 | #define ME1400D_CLK_SRC_0_REG 0x005C /**< Offset of clock source register 0. */ | ||
84 | #define ME1400D_CLK_SRC_1_REG 0x005D /**< Offset of clock source register 1. */ | ||
85 | #define ME1400D_CLK_SRC_2_REG 0x005E /**< Offset of clock source register 2. */ | ||
86 | |||
87 | /* ME4600 register offsets */ | ||
88 | #define ME4600_8254_0_VAL_REG 0x0000 /**< Offset of 8254 A counter 0 value register. */ | ||
89 | #define ME4600_8254_1_VAL_REG 0x0001 /**< Offset of 8254 A counter 0 value register. */ | ||
90 | #define ME4600_8254_2_VAL_REG 0x0002 /**< Offset of 8254 A counter 0 value register. */ | ||
91 | #define ME4600_8254_CTRL_REG 0x0003 /**< Offset of 8254 A control register. */ | ||
92 | |||
93 | /* Command words for 8254 control register */ | ||
94 | #define ME8254_CTRL_SC0 0x00 /**< Counter 0 selection. */ | ||
95 | #define ME8254_CTRL_SC1 0x40 /**< Counter 1 selection. */ | ||
96 | #define ME8254_CTRL_SC2 0x80 /**< Counter 2 selection. */ | ||
97 | |||
98 | #define ME8254_CTRL_TLO 0x00 /**< Counter latching operation. */ | ||
99 | #define ME8254_CTRL_LSB 0x10 /**< Only read LSB. */ | ||
100 | #define ME8254_CTRL_MSB 0x20 /**< Only read MSB. */ | ||
101 | #define ME8254_CTRL_LM 0x30 /**< First read LSB, then MSB. */ | ||
102 | |||
103 | #define ME8254_CTRL_M0 0x00 /**< Mode 0 selection. */ | ||
104 | #define ME8254_CTRL_M1 0x02 /**< Mode 1 selection. */ | ||
105 | #define ME8254_CTRL_M2 0x04 /**< Mode 2 selection. */ | ||
106 | #define ME8254_CTRL_M3 0x06 /**< Mode 3 selection. */ | ||
107 | #define ME8254_CTRL_M4 0x08 /**< Mode 4 selection. */ | ||
108 | #define ME8254_CTRL_M5 0x0A /**< Mode 5 selection. */ | ||
109 | |||
110 | #define ME8254_CTRL_BIN 0x00 /**< Binary counter. */ | ||
111 | #define ME8254_CTRL_BCD 0x01 /**< BCD counter. */ | ||
112 | |||
113 | /* ME-1400 A/B clock source register bits */ | ||
114 | #define ME1400AB_8254_A_0_CLK_SRC_1MHZ (0 << 7) /**< 1MHz clock. */ | ||
115 | #define ME1400AB_8254_A_0_CLK_SRC_10MHZ (1 << 7) /**< 10MHz clock. */ | ||
116 | #define ME1400AB_8254_A_0_CLK_SRC_PIN (0 << 6) /**< CLK 0 to SUB-D. */ | ||
117 | #define ME1400AB_8254_A_0_CLK_SRC_QUARZ (1 << 6) /**< Connect CLK 0 with quarz. */ | ||
118 | |||
119 | #define ME1400AB_8254_A_1_CLK_SRC_PIN (0 << 5) /**< CLK 1 to SUB-D. */ | ||
120 | #define ME1400AB_8254_A_1_CLK_SRC_PREV (1 << 5) /**< Connect OUT 0 with CLK 1. */ | ||
121 | |||
122 | #define ME1400AB_8254_A_2_CLK_SRC_PIN (0 << 4) /**< CLK 2 to SUB-D. */ | ||
123 | #define ME1400AB_8254_A_2_CLK_SRC_PREV (1 << 4) /**< Connect OUT 1 with CLK 2. */ | ||
124 | |||
125 | #define ME1400AB_8254_B_0_CLK_SRC_1MHZ (0 << 3) /**< 1MHz clock. */ | ||
126 | #define ME1400AB_8254_B_0_CLK_SRC_10MHZ (1 << 3) /**< 10MHz clock. */ | ||
127 | #define ME1400AB_8254_B_0_CLK_SRC_PIN (0 << 2) /**< CLK 0 to SUB-D. */ | ||
128 | #define ME1400AB_8254_B_0_CLK_SRC_QUARZ (1 << 2) /**< Connect CLK 0 with quarz. */ | ||
129 | |||
130 | #define ME1400AB_8254_B_1_CLK_SRC_PIN (0 << 1) /**< CLK 1 to SUB-D. */ | ||
131 | #define ME1400AB_8254_B_1_CLK_SRC_PREV (1 << 1) /**< Connect OUT 0 with CLK 1. */ | ||
132 | |||
133 | #define ME1400AB_8254_B_2_CLK_SRC_PIN (0 << 0) /**< CLK 2 to SUB-D. */ | ||
134 | #define ME1400AB_8254_B_2_CLK_SRC_PREV (1 << 0) /**< Connect OUT 1 with CLK 2. */ | ||
135 | |||
136 | /* ME-1400 C/D clock source registers bits */ | ||
137 | #define ME1400CD_8254_ACE_0_CLK_SRC_MASK 0x03 /**< Masks all CLK source bits. */ | ||
138 | #define ME1400CD_8254_ACE_0_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ | ||
139 | #define ME1400CD_8254_ACE_0_CLK_SRC_1MHZ 0x01 /**< Connect CLK to 1MHz. */ | ||
140 | #define ME1400CD_8254_ACE_0_CLK_SRC_10MHZ 0x02 /**< Connect CLK to 10MHz. */ | ||
141 | #define ME1400CD_8254_ACE_0_CLK_SRC_PREV 0x03 /**< Connect CLK to previous counter output on ME-1400 D extension. */ | ||
142 | |||
143 | #define ME1400CD_8254_ACE_1_CLK_SRC_MASK 0x04 /**< Masks all CLK source bits. */ | ||
144 | #define ME1400CD_8254_ACE_1_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ | ||
145 | #define ME1400CD_8254_ACE_1_CLK_SRC_PREV 0x04 /**< Connect CLK to previous counter output. */ | ||
146 | |||
147 | #define ME1400CD_8254_ACE_2_CLK_SRC_MASK 0x08 /**< Masks all CLK source bits. */ | ||
148 | #define ME1400CD_8254_ACE_2_CLK_SRC_PIN 0x00 /**< Connect to SUB-D. */ | ||
149 | #define ME1400CD_8254_ACE_2_CLK_SRC_PREV 0x08 /**< Connect CLK to previous counter output. */ | ||
150 | |||
151 | #define ME1400CD_8254_BD_0_CLK_SRC_MASK 0x30 /**< Masks all CLK source bits. */ | ||
152 | #define ME1400CD_8254_BD_0_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ | ||
153 | #define ME1400CD_8254_BD_0_CLK_SRC_1MHZ 0x10 /**< Connect CLK to 1MHz. */ | ||
154 | #define ME1400CD_8254_BD_0_CLK_SRC_10MHZ 0x20 /**< Connect CLK to 10MHz. */ | ||
155 | #define ME1400CD_8254_BD_0_CLK_SRC_PREV 0x30 /**< Connect CLK to previous counter output. */ | ||
156 | |||
157 | #define ME1400CD_8254_BD_1_CLK_SRC_MASK 0x40 /**< Masks all CLK source bits. */ | ||
158 | #define ME1400CD_8254_BD_1_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ | ||
159 | #define ME1400CD_8254_BD_1_CLK_SRC_PREV 0x40 /**< Connect CLK to previous counter output. */ | ||
160 | |||
161 | #define ME1400CD_8254_BD_2_CLK_SRC_MASK 0x80 /**< Masks all CLK source bits. */ | ||
162 | #define ME1400CD_8254_BD_2_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ | ||
163 | #define ME1400CD_8254_BD_2_CLK_SRC_PREV 0x80 /**< Connect CLK to previous counter output. */ | ||
164 | |||
165 | /* ME-8100 counter registers */ | ||
166 | #define ME8100_COUNTER_REG_0 0x18 //(r,w) | ||
167 | #define ME8100_COUNTER_REG_1 0x1A //(r,w) | ||
168 | #define ME8100_COUNTER_REG_2 0x1C //(r,w) | ||
169 | #define ME8100_COUNTER_CTRL_REG 0x1E //(r,w) | ||
170 | |||
171 | #endif | ||
172 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8255.c b/drivers/staging/meilhaus/me8255.c deleted file mode 100644 index ec9c6389752f..000000000000 --- a/drivers/staging/meilhaus/me8255.c +++ /dev/null | |||
@@ -1,462 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8255.c | ||
3 | * | ||
4 | * @brief 8255 subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef __KERNEL__ | ||
28 | # define __KERNEL__ | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Includes | ||
33 | */ | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/slab.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/io.h> | ||
39 | #include <linux/types.h> | ||
40 | |||
41 | #include "medefines.h" | ||
42 | #include "meinternal.h" | ||
43 | #include "meerror.h" | ||
44 | #include "medebug.h" | ||
45 | |||
46 | #include "me8255_reg.h" | ||
47 | #include "me8255.h" | ||
48 | |||
49 | /* | ||
50 | * Defines | ||
51 | */ | ||
52 | |||
53 | /* | ||
54 | * Functions | ||
55 | */ | ||
56 | |||
57 | static uint8_t get_mode_from_mirror(uint32_t mirror) | ||
58 | { | ||
59 | PDEBUG("executed.\n"); | ||
60 | |||
61 | if (mirror & ME8255_PORT_0_OUTPUT) { | ||
62 | if (mirror & ME8255_PORT_1_OUTPUT) { | ||
63 | if (mirror & ME8255_PORT_2_OUTPUT) { | ||
64 | return ME8255_MODE_OOO; | ||
65 | } else { | ||
66 | return ME8255_MODE_IOO; | ||
67 | } | ||
68 | } else { | ||
69 | if (mirror & ME8255_PORT_2_OUTPUT) { | ||
70 | return ME8255_MODE_OIO; | ||
71 | } else { | ||
72 | return ME8255_MODE_IIO; | ||
73 | } | ||
74 | } | ||
75 | } else { | ||
76 | if (mirror & ME8255_PORT_1_OUTPUT) { | ||
77 | if (mirror & ME8255_PORT_2_OUTPUT) { | ||
78 | return ME8255_MODE_OOI; | ||
79 | } else { | ||
80 | return ME8255_MODE_IOI; | ||
81 | } | ||
82 | } else { | ||
83 | if (mirror & ME8255_PORT_2_OUTPUT) { | ||
84 | return ME8255_MODE_OII; | ||
85 | } else { | ||
86 | return ME8255_MODE_III; | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static int me8255_io_reset_subdevice(struct me_subdevice *subdevice, | ||
93 | struct file *filep, int flags) | ||
94 | { | ||
95 | me8255_subdevice_t *instance; | ||
96 | |||
97 | PDEBUG("executed.\n"); | ||
98 | |||
99 | instance = (me8255_subdevice_t *) subdevice; | ||
100 | |||
101 | if (flags) { | ||
102 | PERROR("Invalid flag specified.\n"); | ||
103 | return ME_ERRNO_INVALID_FLAGS; | ||
104 | } | ||
105 | |||
106 | ME_SUBDEVICE_ENTER; | ||
107 | |||
108 | spin_lock(&instance->subdevice_lock); | ||
109 | spin_lock(instance->ctrl_reg_lock); | ||
110 | *instance->ctrl_reg_mirror &= | ||
111 | ~(ME8255_PORT_0_OUTPUT << instance->dio_idx); | ||
112 | outb(get_mode_from_mirror(*instance->ctrl_reg_mirror), | ||
113 | instance->ctrl_reg); | ||
114 | spin_unlock(instance->ctrl_reg_lock); | ||
115 | |||
116 | outb(0, instance->port_reg); | ||
117 | spin_unlock(&instance->subdevice_lock); | ||
118 | |||
119 | ME_SUBDEVICE_EXIT; | ||
120 | |||
121 | return ME_ERRNO_SUCCESS; | ||
122 | } | ||
123 | |||
124 | static int me8255_io_single_config(struct me_subdevice *subdevice, | ||
125 | struct file *filep, | ||
126 | int channel, | ||
127 | int single_config, | ||
128 | int ref, | ||
129 | int trig_chan, | ||
130 | int trig_type, int trig_edge, int flags) | ||
131 | { | ||
132 | me8255_subdevice_t *instance; | ||
133 | int err = ME_ERRNO_SUCCESS; | ||
134 | |||
135 | PDEBUG("executed.\n"); | ||
136 | |||
137 | instance = (me8255_subdevice_t *) subdevice; | ||
138 | |||
139 | if (flags & ~ME_IO_SINGLE_CONFIG_DIO_BYTE) { | ||
140 | PERROR("Invalid flag specified.\n"); | ||
141 | return ME_ERRNO_INVALID_FLAGS; | ||
142 | } | ||
143 | |||
144 | if (channel) { | ||
145 | PERROR("Invalid channel.\n"); | ||
146 | return ME_ERRNO_INVALID_CHANNEL; | ||
147 | } | ||
148 | |||
149 | ME_SUBDEVICE_ENTER; | ||
150 | |||
151 | spin_lock(&instance->subdevice_lock); | ||
152 | if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { | ||
153 | spin_lock(instance->ctrl_reg_lock); | ||
154 | *instance->ctrl_reg_mirror &= | ||
155 | ~(ME8255_PORT_0_OUTPUT << instance->dio_idx); | ||
156 | outb(get_mode_from_mirror(*instance->ctrl_reg_mirror), | ||
157 | instance->ctrl_reg); | ||
158 | spin_unlock(instance->ctrl_reg_lock); | ||
159 | } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { | ||
160 | spin_lock(instance->ctrl_reg_lock); | ||
161 | *instance->ctrl_reg_mirror |= | ||
162 | (ME8255_PORT_0_OUTPUT << instance->dio_idx); | ||
163 | outb(get_mode_from_mirror(*instance->ctrl_reg_mirror), | ||
164 | instance->ctrl_reg); | ||
165 | spin_unlock(instance->ctrl_reg_lock); | ||
166 | } else { | ||
167 | PERROR("Invalid port direction.\n"); | ||
168 | err = ME_ERRNO_INVALID_SINGLE_CONFIG; | ||
169 | } | ||
170 | spin_unlock(&instance->subdevice_lock); | ||
171 | |||
172 | ME_SUBDEVICE_EXIT; | ||
173 | |||
174 | return err; | ||
175 | } | ||
176 | |||
177 | static int me8255_io_single_read(struct me_subdevice *subdevice, | ||
178 | struct file *filep, | ||
179 | int channel, | ||
180 | int *value, int time_out, int flags) | ||
181 | { | ||
182 | me8255_subdevice_t *instance; | ||
183 | int err = ME_ERRNO_SUCCESS; | ||
184 | |||
185 | PDEBUG("executed.\n"); | ||
186 | |||
187 | instance = (me8255_subdevice_t *) subdevice; | ||
188 | |||
189 | ME_SUBDEVICE_ENTER; | ||
190 | |||
191 | spin_lock(&instance->subdevice_lock); | ||
192 | switch (flags) { | ||
193 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
194 | if ((channel >= 0) && (channel < 8)) { | ||
195 | *value = inb(instance->port_reg) & (0x1 << channel); | ||
196 | } else { | ||
197 | PERROR("Invalid bit number.\n"); | ||
198 | err = ME_ERRNO_INVALID_CHANNEL; | ||
199 | } | ||
200 | break; | ||
201 | |||
202 | case ME_IO_SINGLE_NO_FLAGS: | ||
203 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
204 | if (channel == 0) { | ||
205 | *value = inb(instance->port_reg); | ||
206 | } else { | ||
207 | PERROR("Invalid byte number.\n"); | ||
208 | err = ME_ERRNO_INVALID_CHANNEL; | ||
209 | } | ||
210 | break; | ||
211 | |||
212 | default: | ||
213 | PERROR("Invalid flags specified.\n"); | ||
214 | err = ME_ERRNO_INVALID_FLAGS; | ||
215 | } | ||
216 | spin_unlock(&instance->subdevice_lock); | ||
217 | |||
218 | ME_SUBDEVICE_EXIT; | ||
219 | |||
220 | return err; | ||
221 | } | ||
222 | |||
223 | static int me8255_io_single_write(struct me_subdevice *subdevice, | ||
224 | struct file *filep, | ||
225 | int channel, | ||
226 | int value, int time_out, int flags) | ||
227 | { | ||
228 | me8255_subdevice_t *instance; | ||
229 | uint8_t byte; | ||
230 | int err = ME_ERRNO_SUCCESS; | ||
231 | |||
232 | PDEBUG("executed.\n"); | ||
233 | |||
234 | instance = (me8255_subdevice_t *) subdevice; | ||
235 | |||
236 | ME_SUBDEVICE_ENTER; | ||
237 | |||
238 | spin_lock(&instance->subdevice_lock); | ||
239 | switch (flags) { | ||
240 | case ME_IO_SINGLE_TYPE_DIO_BIT: | ||
241 | if ((channel >= 0) && (channel < 8)) { | ||
242 | if (*instance-> | ||
243 | ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT << | ||
244 | instance->dio_idx)) { | ||
245 | byte = inb(instance->port_reg); | ||
246 | |||
247 | if (value) | ||
248 | byte |= 0x1 << channel; | ||
249 | else | ||
250 | byte &= ~(0x1 << channel); | ||
251 | |||
252 | outb(byte, instance->port_reg); | ||
253 | } else { | ||
254 | PERROR("Port not in output mode.\n"); | ||
255 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
256 | } | ||
257 | } else { | ||
258 | PERROR("Invalid bit number.\n"); | ||
259 | err = ME_ERRNO_INVALID_CHANNEL; | ||
260 | } | ||
261 | break; | ||
262 | |||
263 | case ME_IO_SINGLE_NO_FLAGS: | ||
264 | case ME_IO_SINGLE_TYPE_DIO_BYTE: | ||
265 | if (channel == 0) { | ||
266 | if (*instance-> | ||
267 | ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT << | ||
268 | instance->dio_idx)) { | ||
269 | outb(value, instance->port_reg); | ||
270 | } else { | ||
271 | PERROR("Port not in output mode.\n"); | ||
272 | err = ME_ERRNO_PREVIOUS_CONFIG; | ||
273 | } | ||
274 | } else { | ||
275 | PERROR("Invalid byte number.\n"); | ||
276 | err = ME_ERRNO_INVALID_CHANNEL; | ||
277 | } | ||
278 | break; | ||
279 | |||
280 | default: | ||
281 | PERROR("Invalid flags specified.\n"); | ||
282 | err = ME_ERRNO_INVALID_FLAGS; | ||
283 | } | ||
284 | spin_unlock(&instance->subdevice_lock); | ||
285 | |||
286 | ME_SUBDEVICE_EXIT; | ||
287 | |||
288 | return err; | ||
289 | } | ||
290 | |||
291 | static int me8255_query_number_channels(struct me_subdevice *subdevice, | ||
292 | int *number) | ||
293 | { | ||
294 | PDEBUG("executed.\n"); | ||
295 | *number = ME8255_NUMBER_CHANNELS; | ||
296 | return ME_ERRNO_SUCCESS; | ||
297 | } | ||
298 | |||
299 | static int me8255_query_subdevice_type(struct me_subdevice *subdevice, | ||
300 | int *type, int *subtype) | ||
301 | { | ||
302 | PDEBUG("executed.\n"); | ||
303 | *type = ME_TYPE_DIO; | ||
304 | *subtype = ME_SUBTYPE_SINGLE; | ||
305 | return ME_ERRNO_SUCCESS; | ||
306 | } | ||
307 | |||
308 | static int me8255_query_subdevice_caps(struct me_subdevice *subdevice, | ||
309 | int *caps) | ||
310 | { | ||
311 | PDEBUG("executed.\n"); | ||
312 | *caps = ME_CAPS_DIO_DIR_BYTE; | ||
313 | return ME_ERRNO_SUCCESS; | ||
314 | } | ||
315 | |||
316 | me8255_subdevice_t *me8255_constructor(uint32_t device_id, | ||
317 | uint32_t reg_base, | ||
318 | unsigned int me8255_idx, | ||
319 | unsigned int dio_idx, | ||
320 | int *ctrl_reg_mirror, | ||
321 | spinlock_t *ctrl_reg_lock) | ||
322 | { | ||
323 | me8255_subdevice_t *subdevice; | ||
324 | int err; | ||
325 | |||
326 | PDEBUG("executed.\n"); | ||
327 | |||
328 | /* Allocate memory for subdevice instance */ | ||
329 | subdevice = kmalloc(sizeof(me8255_subdevice_t), GFP_KERNEL); | ||
330 | |||
331 | if (!subdevice) { | ||
332 | PERROR("Cannot get memory for 8255 instance.\n"); | ||
333 | return NULL; | ||
334 | } | ||
335 | |||
336 | memset(subdevice, 0, sizeof(me8255_subdevice_t)); | ||
337 | |||
338 | /* Check if counter index is out of range */ | ||
339 | |||
340 | if (dio_idx > 2) { | ||
341 | PERROR("DIO index is out of range.\n"); | ||
342 | kfree(subdevice); | ||
343 | return NULL; | ||
344 | } | ||
345 | |||
346 | /* Initialize subdevice base class */ | ||
347 | err = me_subdevice_init(&subdevice->base); | ||
348 | |||
349 | if (err) { | ||
350 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
351 | kfree(subdevice); | ||
352 | return NULL; | ||
353 | } | ||
354 | // Initialize spin locks. | ||
355 | spin_lock_init(&subdevice->subdevice_lock); | ||
356 | |||
357 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
358 | |||
359 | /* Save the pointer to global port settings */ | ||
360 | subdevice->ctrl_reg_mirror = ctrl_reg_mirror; | ||
361 | |||
362 | /* Save type of Meilhaus device */ | ||
363 | subdevice->device_id = device_id; | ||
364 | |||
365 | /* Save the indices */ | ||
366 | subdevice->me8255_idx = me8255_idx; | ||
367 | subdevice->dio_idx = dio_idx; | ||
368 | |||
369 | /* Do device specific initialization */ | ||
370 | switch (device_id) { | ||
371 | case PCI_DEVICE_ID_MEILHAUS_ME1400: | ||
372 | case PCI_DEVICE_ID_MEILHAUS_ME14E0: | ||
373 | |||
374 | case PCI_DEVICE_ID_MEILHAUS_ME140A: | ||
375 | case PCI_DEVICE_ID_MEILHAUS_ME14EA: | ||
376 | /* Check if 8255 index is out of range */ | ||
377 | if (me8255_idx > 0) { | ||
378 | PERROR("8255 index is out of range.\n"); | ||
379 | me_subdevice_deinit(&subdevice->base); | ||
380 | kfree(subdevice); | ||
381 | return NULL; | ||
382 | } | ||
383 | |||
384 | case PCI_DEVICE_ID_MEILHAUS_ME140B: /* Fall through */ | ||
385 | case PCI_DEVICE_ID_MEILHAUS_ME14EB: | ||
386 | /* Check if 8255 index is out of range */ | ||
387 | if (me8255_idx > 1) { | ||
388 | PERROR("8255 index is out of range.\n"); | ||
389 | me_subdevice_deinit(&subdevice->base); | ||
390 | kfree(subdevice); | ||
391 | return NULL; | ||
392 | } | ||
393 | |||
394 | /* Get the registers */ | ||
395 | if (me8255_idx == 0) { | ||
396 | subdevice->ctrl_reg = reg_base + ME1400AB_PORT_A_CTRL; | ||
397 | subdevice->port_reg = | ||
398 | reg_base + ME1400AB_PORT_A_0 + dio_idx; | ||
399 | } else if (me8255_idx == 1) { | ||
400 | subdevice->ctrl_reg = reg_base + ME1400AB_PORT_B_CTRL; | ||
401 | subdevice->port_reg = | ||
402 | reg_base + ME1400AB_PORT_B_0 + dio_idx; | ||
403 | } | ||
404 | |||
405 | break; | ||
406 | |||
407 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
408 | /* Check if 8255 index is out of range */ | ||
409 | if (me8255_idx > 0) { | ||
410 | PERROR("8255 index is out of range.\n"); | ||
411 | me_subdevice_deinit(&subdevice->base); | ||
412 | kfree(subdevice); | ||
413 | return NULL; | ||
414 | } | ||
415 | |||
416 | case PCI_DEVICE_ID_MEILHAUS_ME140D: /* Fall through */ | ||
417 | /* Check if 8255 index is out of range */ | ||
418 | if (me8255_idx > 1) { | ||
419 | PERROR("8255 index is out of range.\n"); | ||
420 | me_subdevice_deinit(&subdevice->base); | ||
421 | kfree(subdevice); | ||
422 | return NULL; | ||
423 | } | ||
424 | |||
425 | /* Get the registers */ | ||
426 | if (me8255_idx == 0) { | ||
427 | subdevice->ctrl_reg = reg_base + ME1400CD_PORT_A_CTRL; | ||
428 | subdevice->port_reg = | ||
429 | reg_base + ME1400CD_PORT_A_0 + dio_idx; | ||
430 | } else if (me8255_idx == 1) { | ||
431 | subdevice->ctrl_reg = reg_base + ME1400CD_PORT_B_CTRL; | ||
432 | subdevice->port_reg = | ||
433 | reg_base + ME1400CD_PORT_B_0 + dio_idx; | ||
434 | } | ||
435 | |||
436 | break; | ||
437 | |||
438 | default: | ||
439 | PERROR("Unknown device type. dev ID: 0x%04x\n", device_id); | ||
440 | |||
441 | me_subdevice_deinit(&subdevice->base); | ||
442 | |||
443 | kfree(subdevice); | ||
444 | |||
445 | return NULL; | ||
446 | } | ||
447 | |||
448 | /* Overload subdevice base class methods. */ | ||
449 | subdevice->base.me_subdevice_io_reset_subdevice = | ||
450 | me8255_io_reset_subdevice; | ||
451 | subdevice->base.me_subdevice_io_single_config = me8255_io_single_config; | ||
452 | subdevice->base.me_subdevice_io_single_read = me8255_io_single_read; | ||
453 | subdevice->base.me_subdevice_io_single_write = me8255_io_single_write; | ||
454 | subdevice->base.me_subdevice_query_number_channels = | ||
455 | me8255_query_number_channels; | ||
456 | subdevice->base.me_subdevice_query_subdevice_type = | ||
457 | me8255_query_subdevice_type; | ||
458 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
459 | me8255_query_subdevice_caps; | ||
460 | |||
461 | return subdevice; | ||
462 | } | ||
diff --git a/drivers/staging/meilhaus/me8255.h b/drivers/staging/meilhaus/me8255.h deleted file mode 100644 index 338230052b3c..000000000000 --- a/drivers/staging/meilhaus/me8255.h +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8255.h | ||
3 | * | ||
4 | * @brief Meilhaus PIO 8255 implementation. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME8255_H_ | ||
10 | #define _ME8255_H_ | ||
11 | |||
12 | #include "mesubdevice.h" | ||
13 | #include "meslock.h" | ||
14 | |||
15 | #ifdef __KERNEL__ | ||
16 | |||
17 | /** | ||
18 | * @brief The 8255 subdevice class. | ||
19 | */ | ||
20 | typedef struct me8255_subdevice { | ||
21 | /* Inheritance */ | ||
22 | me_subdevice_t base; /**< The subdevice base class. */ | ||
23 | |||
24 | /* Attributes */ | ||
25 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
26 | |||
27 | int *ctrl_reg_mirror; /**< Pointer to mirror of the control register. */ | ||
28 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg and #ctrl_reg_mirror from concurrent access. */ | ||
29 | |||
30 | uint32_t device_id; /**< The PCI device id of the device holding the 8255 chip. */ | ||
31 | int me8255_idx; /**< The index of the 8255 chip on the device. */ | ||
32 | int dio_idx; /**< The index of the DIO port on the 8255 chip. */ | ||
33 | |||
34 | unsigned long port_reg; /**< Register to read or write a value from or to the port respectively. */ | ||
35 | unsigned long ctrl_reg; /**< Register to configure the 8255 modes. */ | ||
36 | } me8255_subdevice_t; | ||
37 | |||
38 | /** | ||
39 | * @brief The constructor to generate a 8255 instance. | ||
40 | * | ||
41 | * @param device_id The kind of Meilhaus device holding the 8255. | ||
42 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
43 | * @param me8255_idx The index of the 8255 chip on the Meilhaus device. | ||
44 | * @param dio_idx The index of the counter inside a 8255 chip. | ||
45 | * @param ctr_reg_mirror Pointer to mirror of control register. | ||
46 | * @param ctrl_reg_lock Pointer to spin lock protecting the 8255 control register and #ctrl_reg_mirror from concurrent access. | ||
47 | * | ||
48 | * @return Pointer to new instance on success.\n | ||
49 | * NULL on error. | ||
50 | */ | ||
51 | me8255_subdevice_t *me8255_constructor(uint32_t device_id, | ||
52 | uint32_t reg_base, | ||
53 | unsigned int me8255_idx, | ||
54 | unsigned int dio_idx, | ||
55 | int *ctrl_reg_mirror, | ||
56 | spinlock_t * ctrl_reg_lock); | ||
57 | |||
58 | #endif | ||
59 | #endif | ||
diff --git a/drivers/staging/meilhaus/me8255_reg.h b/drivers/staging/meilhaus/me8255_reg.h deleted file mode 100644 index d1dea1a447f6..000000000000 --- a/drivers/staging/meilhaus/me8255_reg.h +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /** | ||
2 | * @file me8255_reg.h | ||
3 | * | ||
4 | * @brief 8255 counter register definitions. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME8255_REG_H_ | ||
10 | #define _ME8255_REG_H_ | ||
11 | |||
12 | #ifdef __KERNEL__ | ||
13 | |||
14 | #define ME8255_NUMBER_CHANNELS 8 /**< The number of channels per 8255 port. */ | ||
15 | |||
16 | #define ME1400AB_PORT_A_0 0x0000 /**< Port 0 offset. */ | ||
17 | #define ME1400AB_PORT_A_1 0x0001 /**< Port 1 offset. */ | ||
18 | #define ME1400AB_PORT_A_2 0x0002 /**< Port 2 offset. */ | ||
19 | #define ME1400AB_PORT_A_CTRL 0x0003 /**< Control register for 8255 A. */ | ||
20 | |||
21 | #define ME1400AB_PORT_B_0 0x0008 /**< Port 0 offset. */ | ||
22 | #define ME1400AB_PORT_B_1 0x0009 /**< Port 1 offset. */ | ||
23 | #define ME1400AB_PORT_B_2 0x000A /**< Port 2 offset. */ | ||
24 | #define ME1400AB_PORT_B_CTRL 0x000B /**< Control register for 8255 B. */ | ||
25 | |||
26 | #define ME1400CD_PORT_A_0 0x0000 /**< Port 0 offset. */ | ||
27 | #define ME1400CD_PORT_A_1 0x0001 /**< Port 1 offset. */ | ||
28 | #define ME1400CD_PORT_A_2 0x0002 /**< Port 2 offset. */ | ||
29 | #define ME1400CD_PORT_A_CTRL 0x0003 /**< Control register for 8255 A. */ | ||
30 | |||
31 | #define ME1400CD_PORT_B_0 0x0040 /**< Port 0 offset. */ | ||
32 | #define ME1400CD_PORT_B_1 0x0041 /**< Port 1 offset. */ | ||
33 | #define ME1400CD_PORT_B_2 0x0042 /**< Port 2 offset. */ | ||
34 | #define ME1400CD_PORT_B_CTRL 0x0043 /**< Control register for 8255 B. */ | ||
35 | |||
36 | #define ME8255_MODE_OOO 0x80 /**< Port 2 = Output, Port 1 = Output, Port 0 = Output */ | ||
37 | #define ME8255_MODE_IOO 0x89 /**< Port 2 = Input, Port 1 = Output, Port 0 = Output */ | ||
38 | #define ME8255_MODE_OIO 0x82 /**< Port 2 = Output, Port 1 = Input, Port 0 = Output */ | ||
39 | #define ME8255_MODE_IIO 0x8B /**< Port 2 = Input, Port 1 = Input, Port 0 = Output */ | ||
40 | #define ME8255_MODE_OOI 0x90 /**< Port 2 = Output, Port 1 = Output, Port 0 = Input */ | ||
41 | #define ME8255_MODE_IOI 0x99 /**< Port 2 = Input, Port 1 = Output, Port 0 = Input */ | ||
42 | #define ME8255_MODE_OII 0x92 /**< Port 2 = Output, Port 1 = Input, Port 0 = Input */ | ||
43 | #define ME8255_MODE_III 0x9B /**< Port 2 = Input, Port 1 = Input, Port 0 = Input */ | ||
44 | |||
45 | #define ME8255_PORT_0_OUTPUT 0x1 /**< If set in mirror then port 0 is in output mode. */ | ||
46 | #define ME8255_PORT_1_OUTPUT 0x2 /**< If set in mirror then port 1 is in output mode. */ | ||
47 | #define ME8255_PORT_2_OUTPUT 0x4 /**< If set in mirror then port 2 is in output mode. */ | ||
48 | |||
49 | #endif | ||
50 | #endif | ||
diff --git a/drivers/staging/meilhaus/mecirc_buf.h b/drivers/staging/meilhaus/mecirc_buf.h deleted file mode 100644 index 516658522ef1..000000000000 --- a/drivers/staging/meilhaus/mecirc_buf.h +++ /dev/null | |||
@@ -1,131 +0,0 @@ | |||
1 | /** | ||
2 | * @file mecirc_buf.h | ||
3 | * | ||
4 | * @brief Meilhaus circular buffer implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef _MECIRC_BUF_H_ | ||
29 | #define _MECIRC_BUF_H_ | ||
30 | |||
31 | # ifdef __KERNEL__ | ||
32 | |||
33 | # ifdef BOSCH | ||
34 | |||
35 | typedef struct me_circ_buf { | ||
36 | unsigned int mask; | ||
37 | // unsigned int count; | ||
38 | uint32_t *buf; | ||
39 | int volatile head; | ||
40 | int volatile tail; | ||
41 | } me_circ_buf_t; | ||
42 | |||
43 | static inline int me_circ_buf_values(me_circ_buf_t * buf) | ||
44 | { | ||
45 | // return ((buf->head - buf->tail) & (buf->count - 1)); | ||
46 | return ((buf->head - buf->tail) & (buf->mask)); | ||
47 | } | ||
48 | |||
49 | static inline int me_circ_buf_space(me_circ_buf_t * buf) | ||
50 | { | ||
51 | // return ((buf->tail - (buf->head + 1)) & (buf->count - 1)); | ||
52 | return ((buf->tail - (buf->head + 1)) & (buf->mask)); | ||
53 | } | ||
54 | |||
55 | static inline int me_circ_buf_values_to_end(me_circ_buf_t * buf) | ||
56 | { | ||
57 | int end; | ||
58 | int n; | ||
59 | // end = buf->count - buf->tail; | ||
60 | // n = (buf->head + end) & (buf->count - 1); | ||
61 | end = buf->mask + 1 - buf->tail; | ||
62 | n = (buf->head + end) & (buf->mask); | ||
63 | return (n < end) ? n : end; | ||
64 | } | ||
65 | |||
66 | static inline int me_circ_buf_space_to_end(me_circ_buf_t * buf) | ||
67 | { | ||
68 | int end; | ||
69 | int n; | ||
70 | |||
71 | // end = buf->count - 1 - buf->head; | ||
72 | // n = (end + buf->tail) & (buf->count - 1); | ||
73 | end = buf->mask - buf->head; | ||
74 | n = (end + buf->tail) & (buf->mask); | ||
75 | return (n <= end) ? n : (end + 1); | ||
76 | } | ||
77 | |||
78 | #define _CBUFF_32b_t | ||
79 | |||
80 | # else //~BOSCH | ||
81 | /// @note buf->mask = buf->count-1 = ME4600_AI_CIRC_BUF_COUNT-1 | ||
82 | |||
83 | # ifdef _CBUFF_32b_t | ||
84 | //32 bit | ||
85 | typedef struct me_circ_buf_32b { | ||
86 | int volatile head; | ||
87 | int volatile tail; | ||
88 | unsigned int mask; //buffor size-1 must be 2^n-1 to work | ||
89 | uint32_t *buf; | ||
90 | } me_circ_buf_t; | ||
91 | # else | ||
92 | //16 bit | ||
93 | typedef struct me_circ_buf_16b { | ||
94 | int volatile head; | ||
95 | int volatile tail; | ||
96 | unsigned int mask; //buffor size-1 must be 2^n-1 to work | ||
97 | uint16_t *buf; | ||
98 | } me_circ_buf_t; | ||
99 | # endif //_CBUFF_32b_t | ||
100 | |||
101 | /** How many values is in buffer */ | ||
102 | static inline int me_circ_buf_values(me_circ_buf_t * buf) | ||
103 | { | ||
104 | return ((buf->head - buf->tail) & (buf->mask)); | ||
105 | } | ||
106 | |||
107 | /** How many space left */ | ||
108 | static inline int me_circ_buf_space(me_circ_buf_t * buf) | ||
109 | { | ||
110 | return ((buf->tail - (buf->head + 1)) & (buf->mask)); | ||
111 | } | ||
112 | |||
113 | /** How many values can be read from buffor in one chunck. */ | ||
114 | static inline int me_circ_buf_values_to_end(me_circ_buf_t * buf) | ||
115 | { | ||
116 | return (buf->tail <= | ||
117 | buf->head) ? (buf->head - buf->tail) : (buf->mask - buf->tail + | ||
118 | 1); | ||
119 | } | ||
120 | |||
121 | /** How many values can be write to buffer in one chunck. */ | ||
122 | static inline int me_circ_buf_space_to_end(me_circ_buf_t * buf) | ||
123 | { | ||
124 | return (buf->tail <= | ||
125 | buf->head) ? (buf->mask - buf->head + 1) : (buf->tail - | ||
126 | buf->head - 1); | ||
127 | } | ||
128 | |||
129 | # endif //BOSCH | ||
130 | # endif //__KERNEL__ | ||
131 | #endif //_MECIRC_BUF_H_ | ||
diff --git a/drivers/staging/meilhaus/mecommon.h b/drivers/staging/meilhaus/mecommon.h deleted file mode 100644 index ef47c384e018..000000000000 --- a/drivers/staging/meilhaus/mecommon.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File :mecommon.h | ||
5 | * Author :GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | * Author :KG (Krzysztof Gantzke) <k.gantzke@meilhaus.de> | ||
7 | */ | ||
8 | |||
9 | #ifndef _MECOMMON_H_ | ||
10 | #define _MECOMMON_H_ | ||
11 | |||
12 | /*================================================================== | ||
13 | The version of this release | ||
14 | ================================================================*/ | ||
15 | |||
16 | #ifndef ME_VERSION_DRIVER | ||
17 | /* Unknown version */ | ||
18 | # define ME_VERSION_DRIVER 0xFFFFFFFF | ||
19 | #endif | ||
20 | |||
21 | #ifndef LIBMEDRIVER_VERSION | ||
22 | /* Unknown version */ | ||
23 | # define LIBMEDRIVER_VERSION 0xFFFFFFFF | ||
24 | #endif | ||
25 | |||
26 | #endif | ||
diff --git a/drivers/staging/meilhaus/medebug.h b/drivers/staging/meilhaus/medebug.h deleted file mode 100644 index dcfb97c26fd1..000000000000 --- a/drivers/staging/meilhaus/medebug.h +++ /dev/null | |||
@@ -1,125 +0,0 @@ | |||
1 | /** | ||
2 | * @file medebug.h | ||
3 | * | ||
4 | * @brief Debugging defines. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | #ifndef _MEDEBUG_H_ | ||
11 | #define _MEDEBUG_H_ | ||
12 | |||
13 | #ifdef __KERNEL__ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | |||
17 | //Messages control. | ||
18 | |||
19 | #ifdef MEDEBUG_TEST_ALL /* Switch to enable all info messages. */ | ||
20 | # ifndef MEDEBUG_TEST | ||
21 | # define MEDEBUG_TEST | ||
22 | # endif | ||
23 | # ifndef MEDEBUG_TEST_INFO | ||
24 | # define MEDEBUG_TEST_INFO | ||
25 | # endif | ||
26 | # ifndef MEDEBUG_DEBUG_REG | ||
27 | # define MEDEBUG_DEBUG_REG /* Switch to enable registry access debuging messages. */ | ||
28 | # endif | ||
29 | # ifndef MEDEBUG_DEBUG_LOCKS | ||
30 | # define MEDEBUG_DEBUG_LOCKS /* Switch to enable locking messages. */ | ||
31 | # endif | ||
32 | #endif | ||
33 | |||
34 | #ifdef MEDEBUG_TEST_INFO /* Switch to enable info and test messages. */ | ||
35 | # ifndef MEDEBUG_INFO | ||
36 | # define MEDEBUG_INFO /* Switch to enable info messages. */ | ||
37 | # endif | ||
38 | # ifndef MEDEBUG_TEST | ||
39 | # define MEDEBUG_TEST | ||
40 | # endif | ||
41 | #endif | ||
42 | |||
43 | #ifdef MEDEBUG_TEST /* Switch to enable debug test messages. */ | ||
44 | # ifndef MEDEBUG_DEBUG | ||
45 | # define MEDEBUG_DEBUG /* Switch to enable debug messages. */ | ||
46 | # endif | ||
47 | # ifndef MEDEBUG_ERROR | ||
48 | # define MEDEBUG_ERROR /* Switch to enable error messages. */ | ||
49 | # endif | ||
50 | #endif | ||
51 | |||
52 | #ifdef MEDEBUG_ERROR /* Switch to enable error messages. */ | ||
53 | # ifndef MEDEBUG_ERROR_CRITICAL /* Also critical error messages. */ | ||
54 | # define MEDEBUG_ERROR_CRITICAL /* Switch to enable high importance error messages. */ | ||
55 | # endif | ||
56 | #endif | ||
57 | |||
58 | #undef PDEBUG /* Only to be sure. */ | ||
59 | #undef PINFO /* Only to be sure. */ | ||
60 | #undef PERROR /* Only to be sure. */ | ||
61 | #undef PERROR_CRITICAL /* Only to be sure. */ | ||
62 | #undef PDEBUG_REG /* Only to be sure. */ | ||
63 | #undef PDEBUG_LOCKS /* Only to be sure. */ | ||
64 | #undef PSECURITY /* Only to be sure. */ | ||
65 | #undef PLOG /* Only to be sure. */ | ||
66 | |||
67 | #ifdef MEDEBUG_DEBUG | ||
68 | # define PDEBUG(fmt, args...) \ | ||
69 | printk(KERN_DEBUG"ME_DRV D: <%s> " fmt, __func__, ##args) | ||
70 | #else | ||
71 | # define PDEBUG(fmt, args...) | ||
72 | #endif | ||
73 | |||
74 | #ifdef MEDEBUG_DEBUG_LOCKS | ||
75 | # define PDEBUG_LOCKS(fmt, args...) \ | ||
76 | printk(KERN_DEBUG"ME_DRV L: <%s> " fmt, __func__, ##args) | ||
77 | #else | ||
78 | # define PDEBUG_LOCKS(fmt, args...) | ||
79 | #endif | ||
80 | |||
81 | #ifdef MEDEBUG_DEBUG_REG | ||
82 | # define PDEBUG_REG(fmt, args...) \ | ||
83 | printk(KERN_DEBUG"ME_DRV R: <%s:%d> REG:" fmt, __func__, __LINE__, ##args) | ||
84 | #else | ||
85 | # define PDEBUG_REG(fmt, args...) | ||
86 | #endif | ||
87 | |||
88 | #ifdef MEDEBUG_INFO | ||
89 | # define PINFO(fmt, args...) \ | ||
90 | printk(KERN_INFO"ME_DRV I: " fmt, ##args) | ||
91 | #else | ||
92 | # define PINFO(fmt, args...) | ||
93 | #endif | ||
94 | |||
95 | #ifdef MEDEBUG_ERROR | ||
96 | # define PERROR(fmt, args...) \ | ||
97 | printk(KERN_ERR"ME_DRV E: <%s:%i> " fmt, __FILE__, __LINE__, ##args) | ||
98 | #else | ||
99 | # define PERROR(fmt, args...) | ||
100 | #endif | ||
101 | |||
102 | #ifdef MEDEBUG_ERROR_CRITICAL | ||
103 | # define PERROR_CRITICAL(fmt, args...) \ | ||
104 | printk(KERN_CRIT"ME_DRV C: <%s:%i> " fmt, __FILE__, __LINE__, ##args) | ||
105 | #else | ||
106 | # define PERROR_CRITICAL(fmt, args...) | ||
107 | #endif | ||
108 | |||
109 | //This debug is only to detect logical errors! | ||
110 | # define PSECURITY(fmt, args...) \ | ||
111 | printk(KERN_CRIT"ME_DRV SECURITY: <%s:%s:%i> " fmt, __FILE__, __func__, __LINE__, ##args) | ||
112 | //This debug is to keep track in customers' system | ||
113 | # define PLOG(fmt, args...) \ | ||
114 | printk(KERN_INFO"ME_DRV: " fmt, ##args) | ||
115 | |||
116 | //This debug is to check new parts during development | ||
117 | #ifdef MEDEBUG_DEVELOP | ||
118 | # define PDEVELOP(fmt, args...) \ | ||
119 | printk(KERN_CRIT"ME_DRV: <%s:%s:%i> " fmt, __FILE__, __func__, __LINE__, ##args) | ||
120 | #else | ||
121 | # define PDEVELOP(fmt, args...) | ||
122 | #endif | ||
123 | |||
124 | #endif //__KERNEL__ | ||
125 | #endif //_MEDEBUG_H_ | ||
diff --git a/drivers/staging/meilhaus/medefines.h b/drivers/staging/meilhaus/medefines.h deleted file mode 100644 index 6158ef5b80e6..000000000000 --- a/drivers/staging/meilhaus/medefines.h +++ /dev/null | |||
@@ -1,449 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : medefines.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | * Author : KG (Krzysztof Gantzke) <k.gantzke@meilhaus.de> | ||
7 | */ | ||
8 | |||
9 | #ifndef _MEDEFINES_H_ | ||
10 | #define _MEDEFINES_H_ | ||
11 | |||
12 | /*================================================================== | ||
13 | General | ||
14 | ================================================================*/ | ||
15 | |||
16 | #define ME_VALUE_NOT_USED 0x0 | ||
17 | #define ME_VALUE_INVALID ~0x0 | ||
18 | |||
19 | /*================================================================== | ||
20 | Defines common to access functions | ||
21 | ================================================================*/ | ||
22 | |||
23 | #define ME_LOCK_RELEASE 0x00010001 | ||
24 | #define ME_LOCK_SET 0x00010002 | ||
25 | #define ME_LOCK_CHECK 0x00010003 | ||
26 | |||
27 | /*================================================================== | ||
28 | Defines meOpen function | ||
29 | ================================================================*/ | ||
30 | |||
31 | #define ME_OPEN_NO_FLAGS 0x0 | ||
32 | |||
33 | /*================================================================== | ||
34 | Defines meClose function | ||
35 | ================================================================*/ | ||
36 | |||
37 | #define ME_CLOSE_NO_FLAGS 0x0 | ||
38 | |||
39 | /*================================================================== | ||
40 | Defines meLockDriver function | ||
41 | ================================================================*/ | ||
42 | |||
43 | #define ME_LOCK_DRIVER_NO_FLAGS 0x0 | ||
44 | |||
45 | /*================================================================== | ||
46 | Defines meLockDevice function | ||
47 | ================================================================*/ | ||
48 | |||
49 | #define ME_LOCK_DEVICE_NO_FLAGS 0x0 | ||
50 | |||
51 | /*================================================================== | ||
52 | Defines meLockSubdevice function | ||
53 | ================================================================*/ | ||
54 | |||
55 | #define ME_LOCK_SUBDEVICE_NO_FLAGS 0x0 | ||
56 | |||
57 | |||
58 | /*================================================================== | ||
59 | Defines common to error functions | ||
60 | ================================================================*/ | ||
61 | |||
62 | #define ME_ERROR_MSG_MAX_COUNT 256 | ||
63 | |||
64 | #define ME_SWITCH_DISABLE 0x00020001 | ||
65 | #define ME_SWITCH_ENABLE 0x00020002 | ||
66 | |||
67 | /*================================================================== | ||
68 | Defines common to io functions | ||
69 | ================================================================*/ | ||
70 | |||
71 | #define ME_REF_DIO_FIFO_LOW 0x00030001 | ||
72 | #define ME_REF_DIO_FIFO_HIGH 0x00030002 | ||
73 | |||
74 | #define ME_REF_CTR_PREVIOUS 0x00040001 | ||
75 | #define ME_REF_CTR_INTERNAL_1MHZ 0x00040002 | ||
76 | #define ME_REF_CTR_INTERNAL_10MHZ 0x00040003 | ||
77 | #define ME_REF_CTR_EXTERNAL 0x00040004 | ||
78 | |||
79 | #define ME_REF_AI_GROUND 0x00050001 | ||
80 | #define ME_REF_AI_DIFFERENTIAL 0x00050002 | ||
81 | |||
82 | #define ME_REF_AO_GROUND 0x00060001 | ||
83 | |||
84 | #define ME_TRIG_CHAN_DEFAULT 0x00070001 | ||
85 | #define ME_TRIG_CHAN_SYNCHRONOUS 0x00070002 | ||
86 | |||
87 | #define ME_TRIG_TYPE_NONE 0x00000000 | ||
88 | #define ME_TRIG_TYPE_SW 0x00080001 | ||
89 | #define ME_TRIG_TYPE_THRESHOLD 0x00080002 | ||
90 | #define ME_TRIG_TYPE_WINDOW 0x00080003 | ||
91 | #define ME_TRIG_TYPE_EDGE 0x00080004 | ||
92 | #define ME_TRIG_TYPE_SLOPE 0x00080005 | ||
93 | #define ME_TRIG_TYPE_EXT_DIGITAL 0x00080006 | ||
94 | #define ME_TRIG_TYPE_EXT_ANALOG 0x00080007 | ||
95 | #define ME_TRIG_TYPE_PATTERN 0x00080008 | ||
96 | #define ME_TRIG_TYPE_TIMER 0x00080009 | ||
97 | #define ME_TRIG_TYPE_COUNT 0x0008000A | ||
98 | #define ME_TRIG_TYPE_FOLLOW 0x0008000B | ||
99 | |||
100 | #define ME_TRIG_EDGE_NONE 0x00000000 | ||
101 | #define ME_TRIG_EDGE_ABOVE 0x00090001 | ||
102 | #define ME_TRIG_EDGE_BELOW 0x00090002 | ||
103 | #define ME_TRIG_EDGE_ENTRY 0x00090003 | ||
104 | #define ME_TRIG_EDGE_EXIT 0x00090004 | ||
105 | #define ME_TRIG_EDGE_RISING 0x00090005 | ||
106 | #define ME_TRIG_EDGE_FALLING 0x00090006 | ||
107 | #define ME_TRIG_EDGE_ANY 0x00090007 | ||
108 | |||
109 | #define ME_TIMER_ACQ_START 0x000A0001 | ||
110 | #define ME_TIMER_SCAN_START 0x000A0002 | ||
111 | #define ME_TIMER_CONV_START 0x000A0003 | ||
112 | |||
113 | /*================================================================== | ||
114 | Defines for meIOFrequencyToTicks function | ||
115 | ================================================================*/ | ||
116 | |||
117 | #define ME_IO_FREQUENCY_TO_TICKS_NO_FLAGS 0x0 | ||
118 | |||
119 | /*================================================================== | ||
120 | Defines for meIOIrqStart function | ||
121 | ================================================================*/ | ||
122 | |||
123 | #define ME_IRQ_SOURCE_DIO_PATTERN 0x000B0001 | ||
124 | #define ME_IRQ_SOURCE_DIO_MASK 0x000B0002 | ||
125 | #define ME_IRQ_SOURCE_DIO_LINE 0x000B0003 | ||
126 | #define ME_IRQ_SOURCE_DIO_OVER_TEMP 0x000B0004 | ||
127 | |||
128 | #define ME_IRQ_EDGE_NOT_USED 0x00000000 | ||
129 | #define ME_IRQ_EDGE_RISING 0x000C0001 | ||
130 | #define ME_IRQ_EDGE_FALLING 0x000C0002 | ||
131 | #define ME_IRQ_EDGE_ANY 0x000C0003 | ||
132 | |||
133 | /*================================================================== | ||
134 | Defines for meIOIrqStart function | ||
135 | ================================================================*/ | ||
136 | |||
137 | #define ME_IO_IRQ_START_NO_FLAGS 0x000000 | ||
138 | #define ME_IO_IRQ_START_DIO_BIT 0x000001 | ||
139 | #define ME_IO_IRQ_START_DIO_BYTE 0x000002 | ||
140 | #define ME_IO_IRQ_START_DIO_WORD 0x000004 | ||
141 | #define ME_IO_IRQ_START_DIO_DWORD 0x000008 | ||
142 | #define ME_IO_IRQ_START_PATTERN_FILTERING 0x000010 | ||
143 | #define ME_IO_IRQ_START_EXTENDED_STATUS 0x000020 | ||
144 | |||
145 | /*================================================================== | ||
146 | Defines for meIOIrqWait function | ||
147 | ================================================================*/ | ||
148 | |||
149 | #define ME_IO_IRQ_WAIT_NO_FLAGS 0x000000 | ||
150 | #define ME_IO_IRQ_WAIT_NORMAL_STATUS 0x000001 | ||
151 | #define ME_IO_IRQ_WAIT_EXTENDED_STATUS 0x000002 | ||
152 | |||
153 | /*================================================================== | ||
154 | Defines for meIOIrqStop function | ||
155 | ================================================================*/ | ||
156 | |||
157 | #define ME_IO_IRQ_STOP_NO_FLAGS 0x000000 | ||
158 | |||
159 | /*================================================================== | ||
160 | Defines for meIOIrqSetCallback function | ||
161 | ================================================================*/ | ||
162 | |||
163 | #define ME_IO_IRQ_SET_CALLBACK_NO_FLAGS 0x0 | ||
164 | |||
165 | /*================================================================== | ||
166 | Defines for meIOResetDevice function | ||
167 | ================================================================*/ | ||
168 | |||
169 | #define ME_IO_RESET_DEVICE_NO_FLAGS 0x0 | ||
170 | |||
171 | /*================================================================== | ||
172 | Defines for meIOResetSubdevice function | ||
173 | ================================================================*/ | ||
174 | |||
175 | #define ME_IO_RESET_SUBDEVICE_NO_FLAGS 0x0 | ||
176 | |||
177 | /*================================================================== | ||
178 | Defines for meIOSingleConfig function | ||
179 | ================================================================*/ | ||
180 | |||
181 | #define ME_SINGLE_CONFIG_DIO_INPUT 0x000D0001 | ||
182 | #define ME_SINGLE_CONFIG_DIO_OUTPUT 0x000D0002 | ||
183 | #define ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE 0x000D0003 | ||
184 | #define ME_SINGLE_CONFIG_DIO_SINK 0x000D0004 | ||
185 | #define ME_SINGLE_CONFIG_DIO_SOURCE 0x000D0005 | ||
186 | #define ME_SINGLE_CONFIG_DIO_MUX32M 0x000D0006 | ||
187 | #define ME_SINGLE_CONFIG_DIO_DEMUX32 0x000D0007 | ||
188 | #define ME_SINGLE_CONFIG_DIO_BIT_PATTERN 0x000D0008 | ||
189 | |||
190 | #define ME_SINGLE_CONFIG_CTR_8254_MODE_0 0x000E0001 | ||
191 | #define ME_SINGLE_CONFIG_CTR_8254_MODE_1 0x000E0002 | ||
192 | #define ME_SINGLE_CONFIG_CTR_8254_MODE_2 0x000E0003 | ||
193 | #define ME_SINGLE_CONFIG_CTR_8254_MODE_3 0x000E0004 | ||
194 | #define ME_SINGLE_CONFIG_CTR_8254_MODE_4 0x000E0005 | ||
195 | #define ME_SINGLE_CONFIG_CTR_8254_MODE_5 0x000E0006 | ||
196 | |||
197 | #define ME_IO_SINGLE_CONFIG_NO_FLAGS 0x00 | ||
198 | #define ME_IO_SINGLE_CONFIG_DIO_BIT 0x01 | ||
199 | #define ME_IO_SINGLE_CONFIG_DIO_BYTE 0x02 | ||
200 | #define ME_IO_SINGLE_CONFIG_DIO_WORD 0x04 | ||
201 | #define ME_IO_SINGLE_CONFIG_DIO_DWORD 0x08 | ||
202 | #define ME_IO_SINGLE_CONFIG_MULTISIG_LED_ON 0x10 | ||
203 | #define ME_IO_SINGLE_CONFIG_MULTISIG_LED_OFF 0x20 | ||
204 | #define ME_IO_SINGLE_CONFIG_AI_RMS 0x40 | ||
205 | #define ME_IO_SINGLE_CONFIG_CONTINUE 0x80 | ||
206 | |||
207 | /*================================================================== | ||
208 | Defines for meIOSingle function | ||
209 | ================================================================*/ | ||
210 | |||
211 | #define ME_IO_SINGLE_NO_FLAGS 0x0 | ||
212 | #define ME_IO_SINGLE_NONBLOCKING 0x20 | ||
213 | |||
214 | #define ME_DIR_INPUT 0x000F0001 | ||
215 | #define ME_DIR_OUTPUT 0x000F0002 | ||
216 | |||
217 | #define ME_IO_SINGLE_TYPE_NO_FLAGS 0x00 | ||
218 | #define ME_IO_SINGLE_TYPE_DIO_BIT 0x01 | ||
219 | #define ME_IO_SINGLE_TYPE_DIO_BYTE 0x02 | ||
220 | #define ME_IO_SINGLE_TYPE_DIO_WORD 0x04 | ||
221 | #define ME_IO_SINGLE_TYPE_DIO_DWORD 0x08 | ||
222 | #define ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS 0x10 | ||
223 | #define ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING 0x20 | ||
224 | |||
225 | /*================================================================== | ||
226 | Defines for meIOStreamConfig function | ||
227 | ================================================================*/ | ||
228 | |||
229 | #define ME_IO_STREAM_CONFIG_NO_FLAGS 0x0 | ||
230 | #define ME_IO_STREAM_CONFIG_BIT_PATTERN 0x1 | ||
231 | #define ME_IO_STREAM_CONFIG_WRAPAROUND 0x2 | ||
232 | #define ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD 0x4 | ||
233 | #define ME_IO_STREAM_CONFIG_HARDWARE_ONLY 0x8 | ||
234 | |||
235 | #define ME_IO_STREAM_CONFIG_TYPE_NO_FLAGS 0x0 | ||
236 | |||
237 | #define ME_IO_STREAM_TRIGGER_TYPE_NO_FLAGS 0x0 | ||
238 | |||
239 | /*================================================================== | ||
240 | Defines for meIOStreamRead function | ||
241 | ================================================================*/ | ||
242 | |||
243 | #define ME_READ_MODE_BLOCKING 0x00100001 | ||
244 | #define ME_READ_MODE_NONBLOCKING 0x00100002 | ||
245 | |||
246 | #define ME_IO_STREAM_READ_NO_FLAGS 0x0 | ||
247 | #define ME_IO_STREAM_READ_FRAMES 0x1 | ||
248 | |||
249 | /*================================================================== | ||
250 | Defines for meIOStreamWrite function | ||
251 | ================================================================*/ | ||
252 | |||
253 | #define ME_WRITE_MODE_BLOCKING 0x00110001 | ||
254 | #define ME_WRITE_MODE_NONBLOCKING 0x00110002 | ||
255 | #define ME_WRITE_MODE_PRELOAD 0x00110003 | ||
256 | |||
257 | #define ME_IO_STREAM_WRITE_NO_FLAGS 0x00000000 | ||
258 | |||
259 | /*================================================================== | ||
260 | Defines for meIOStreamStart function | ||
261 | ================================================================*/ | ||
262 | |||
263 | #define ME_IO_STREAM_START_NO_FLAGS 0x00000000 | ||
264 | |||
265 | #define ME_START_MODE_BLOCKING 0x00120001 | ||
266 | #define ME_START_MODE_NONBLOCKING 0x00120002 | ||
267 | |||
268 | #define ME_IO_STREAM_START_TYPE_NO_FLAGS 0x0 | ||
269 | #define ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS 0x1 | ||
270 | |||
271 | /*================================================================== | ||
272 | Defines for meIOStreamStop function | ||
273 | ================================================================*/ | ||
274 | |||
275 | #define ME_IO_STREAM_STOP_NO_FLAGS 0x00000000 | ||
276 | #define ME_IO_STREAM_STOP_PRESERVE_BUFFERS 0x00000001 | ||
277 | |||
278 | #define ME_STOP_MODE_IMMEDIATE 0x00130001 | ||
279 | #define ME_STOP_MODE_LAST_VALUE 0x00130002 | ||
280 | |||
281 | #define ME_IO_STREAM_STOP_TYPE_NO_FLAGS 0x00000000 | ||
282 | |||
283 | /*================================================================== | ||
284 | Defines for meIOStreamStatus function | ||
285 | ================================================================*/ | ||
286 | |||
287 | #define ME_WAIT_NONE 0x00140001 | ||
288 | #define ME_WAIT_IDLE 0x00140002 | ||
289 | |||
290 | #define ME_STATUS_INVALID 0x00000000 | ||
291 | #define ME_STATUS_IDLE 0x00150001 | ||
292 | #define ME_STATUS_BUSY 0x00150002 | ||
293 | #define ME_STATUS_ERROR 0x00150003 | ||
294 | |||
295 | #define ME_IO_STREAM_STATUS_NO_FLAGS 0x00000000 | ||
296 | |||
297 | /*================================================================== | ||
298 | Defines for meIOStreamSetCallbacks function | ||
299 | ================================================================*/ | ||
300 | |||
301 | #define ME_IO_STREAM_SET_CALLBACKS_NO_FLAGS 0x00000000 | ||
302 | |||
303 | /*================================================================== | ||
304 | Defines for meIOStreamNewValues function | ||
305 | ================================================================*/ | ||
306 | |||
307 | #define ME_IO_STREAM_NEW_VALUES_NO_FLAGS 0x00000000 | ||
308 | |||
309 | /*================================================================== | ||
310 | Defines for meIOTimeToTicks function | ||
311 | ================================================================*/ | ||
312 | |||
313 | #define ME_IO_STREAM_TIME_TO_TICKS_NO_FLAGS 0x00000000 | ||
314 | |||
315 | /*================================================================== | ||
316 | Defines for module types | ||
317 | ================================================================*/ | ||
318 | |||
319 | #define ME_MODULE_TYPE_MULTISIG_NONE 0x00000000 | ||
320 | #define ME_MODULE_TYPE_MULTISIG_DIFF16_10V 0x00160001 | ||
321 | #define ME_MODULE_TYPE_MULTISIG_DIFF16_20V 0x00160002 | ||
322 | #define ME_MODULE_TYPE_MULTISIG_DIFF16_50V 0x00160003 | ||
323 | #define ME_MODULE_TYPE_MULTISIG_CURRENT16_0_20MA 0x00160004 | ||
324 | #define ME_MODULE_TYPE_MULTISIG_RTD8_PT100 0x00160005 | ||
325 | #define ME_MODULE_TYPE_MULTISIG_RTD8_PT500 0x00160006 | ||
326 | #define ME_MODULE_TYPE_MULTISIG_RTD8_PT1000 0x00160007 | ||
327 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_B 0x00160008 | ||
328 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_E 0x00160009 | ||
329 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_J 0x0016000A | ||
330 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_K 0x0016000B | ||
331 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_N 0x0016000C | ||
332 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_R 0x0016000D | ||
333 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_S 0x0016000E | ||
334 | #define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_T 0x0016000F | ||
335 | #define ME_MODULE_TYPE_MULTISIG_TE8_TEMP_SENSOR 0x00160010 | ||
336 | |||
337 | /*================================================================== | ||
338 | Defines for meQuerySubdeviceCaps function | ||
339 | ================================================================*/ | ||
340 | |||
341 | #define ME_CAPS_NONE 0x00000000 | ||
342 | |||
343 | #define ME_CAPS_DIO_DIR_BIT 0x00000001 | ||
344 | #define ME_CAPS_DIO_DIR_BYTE 0x00000002 | ||
345 | #define ME_CAPS_DIO_DIR_WORD 0x00000004 | ||
346 | #define ME_CAPS_DIO_DIR_DWORD 0x00000008 | ||
347 | #define ME_CAPS_DIO_SINK_SOURCE 0x00000010 | ||
348 | #define ME_CAPS_DIO_BIT_PATTERN_IRQ 0x00000020 | ||
349 | #define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_RISING 0x00000040 | ||
350 | #define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_FALLING 0x00000080 | ||
351 | #define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY 0x00000100 | ||
352 | #define ME_CAPS_DIO_OVER_TEMP_IRQ 0x00000200 | ||
353 | |||
354 | #define ME_CAPS_CTR_CLK_PREVIOUS 0x00000001 | ||
355 | #define ME_CAPS_CTR_CLK_INTERNAL_1MHZ 0x00000002 | ||
356 | #define ME_CAPS_CTR_CLK_INTERNAL_10MHZ 0x00000004 | ||
357 | #define ME_CAPS_CTR_CLK_EXTERNAL 0x00000008 | ||
358 | |||
359 | #define ME_CAPS_AI_TRIG_SYNCHRONOUS 0x00000001 | ||
360 | /// @note Backward compatibility for me1600 in old style. | ||
361 | #define ME_CAPS_AI_TRIG_SIMULTANEOUS ME_CAPS_AI_TRIG_SYNCHRONOUS | ||
362 | #define ME_CAPS_AI_FIFO 0x00000002 | ||
363 | #define ME_CAPS_AI_FIFO_THRESHOLD 0x00000004 | ||
364 | |||
365 | #define ME_CAPS_AO_TRIG_SYNCHRONOUS 0x00000001 | ||
366 | /// @note Backward compatibility for me1600 in old style. | ||
367 | #define ME_CAPS_AO_TRIG_SIMULTANEOUS ME_CAPS_AO_TRIG_SYNCHRONOUS | ||
368 | #define ME_CAPS_AO_FIFO 0x00000002 | ||
369 | #define ME_CAPS_AO_FIFO_THRESHOLD 0x00000004 | ||
370 | |||
371 | #define ME_CAPS_EXT_IRQ_EDGE_RISING 0x00000001 | ||
372 | #define ME_CAPS_EXT_IRQ_EDGE_FALLING 0x00000002 | ||
373 | #define ME_CAPS_EXT_IRQ_EDGE_ANY 0x00000004 | ||
374 | |||
375 | /*================================================================== | ||
376 | Defines for meQuerySubdeviceCapsArgs function | ||
377 | ================================================================*/ | ||
378 | |||
379 | #define ME_CAP_AI_FIFO_SIZE 0x001D0000 | ||
380 | #define ME_CAP_AI_BUFFER_SIZE 0x001D0001 | ||
381 | |||
382 | #define ME_CAP_AO_FIFO_SIZE 0x001F0000 | ||
383 | #define ME_CAP_AO_BUFFER_SIZE 0x001F0001 | ||
384 | |||
385 | #define ME_CAP_CTR_WIDTH 0x00200000 | ||
386 | |||
387 | /*================================================================== | ||
388 | Defines common to query functions | ||
389 | ================================================================*/ | ||
390 | |||
391 | #define ME_UNIT_INVALID 0x00000000 | ||
392 | #define ME_UNIT_VOLT 0x00170001 | ||
393 | #define ME_UNIT_AMPERE 0x00170002 | ||
394 | #define ME_UNIT_ANY 0x00170003 | ||
395 | |||
396 | #define ME_TYPE_INVALID 0x00000000 | ||
397 | #define ME_TYPE_AO 0x00180001 | ||
398 | #define ME_TYPE_AI 0x00180002 | ||
399 | #define ME_TYPE_DIO 0x00180003 | ||
400 | #define ME_TYPE_DO 0x00180004 | ||
401 | #define ME_TYPE_DI 0x00180005 | ||
402 | #define ME_TYPE_CTR 0x00180006 | ||
403 | #define ME_TYPE_EXT_IRQ 0x00180007 | ||
404 | |||
405 | #define ME_SUBTYPE_INVALID 0x00000000 | ||
406 | #define ME_SUBTYPE_SINGLE 0x00190001 | ||
407 | #define ME_SUBTYPE_STREAMING 0x00190002 | ||
408 | #define ME_SUBTYPE_CTR_8254 0x00190003 | ||
409 | #define ME_SUBTYPE_ANY 0x00190004 | ||
410 | |||
411 | #define ME_DEVICE_DRIVER_NAME_MAX_COUNT 64 | ||
412 | #define ME_DEVICE_NAME_MAX_COUNT 64 | ||
413 | |||
414 | #define ME_DEVICE_DESCRIPTION_MAX_COUNT 256 | ||
415 | |||
416 | #define ME_BUS_TYPE_INVALID 0x00000000 | ||
417 | #define ME_BUS_TYPE_PCI 0x001A0001 | ||
418 | #define ME_BUS_TYPE_USB 0x001A0002 | ||
419 | |||
420 | #define ME_PLUGGED_INVALID 0x00000000 | ||
421 | #define ME_PLUGGED_IN 0x001B0001 | ||
422 | #define ME_PLUGGED_OUT 0x001B0002 | ||
423 | |||
424 | #define ME_EXTENSION_TYPE_INVALID 0x00000000 | ||
425 | #define ME_EXTENSION_TYPE_NONE 0x001C0001 | ||
426 | #define ME_EXTENSION_TYPE_MUX32M 0x001C0002 | ||
427 | #define ME_EXTENSION_TYPE_DEMUX32 0x001C0003 | ||
428 | #define ME_EXTENSION_TYPE_MUX32S 0x001C0004 | ||
429 | |||
430 | #define ME_ACCESS_TYPE_INVALID 0x00000000 | ||
431 | #define ME_ACCESS_TYPE_LOCAL 0x001D0001 | ||
432 | #define ME_ACCESS_TYPE_REMOTE 0x001D0002 | ||
433 | |||
434 | /// @note Add by KG | ||
435 | |||
436 | /*================================================================== | ||
437 | Defines for meUtilityPWM | ||
438 | ================================================================*/ | ||
439 | #define ME_PWM_START_CONNECT_INTERNAL 0x00200001 | ||
440 | |||
441 | /* Flags for SingleConfig channels configure */ | ||
442 | #define ME_SINGLE_CHANNEL_NOT_CONFIGURED 0x00 | ||
443 | #define ME_SINGLE_CHANNEL_CONFIGURED 0x01 | ||
444 | |||
445 | /* Define if configuration should be downloaded to driver */ | ||
446 | #define ME_CONFIG_LOAD_NO_FLAGS 0x0 | ||
447 | #define ME_CONFIG_LOAD_TO_DRIVER 0x1 | ||
448 | |||
449 | #endif | ||
diff --git a/drivers/staging/meilhaus/medevice.c b/drivers/staging/meilhaus/medevice.c deleted file mode 100644 index 75aaec0f681b..000000000000 --- a/drivers/staging/meilhaus/medevice.c +++ /dev/null | |||
@@ -1,1740 +0,0 @@ | |||
1 | /** | ||
2 | * @file medevice.c | ||
3 | * | ||
4 | * @brief Meilhaus device base class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #include "mecommon.h" | ||
29 | #include "meinternal.h" | ||
30 | #include "medefines.h" | ||
31 | #include "meerror.h" | ||
32 | |||
33 | #include "medebug.h" | ||
34 | #include "medevice.h" | ||
35 | |||
36 | #ifndef __KERNEL__ | ||
37 | # define __KERNEL__ | ||
38 | #endif | ||
39 | |||
40 | static int me_device_io_irq_start(struct me_device *device, | ||
41 | struct file *filep, | ||
42 | int subdevice, | ||
43 | int channel, | ||
44 | int irq_source, | ||
45 | int irq_edge, int irq_arg, int flags) | ||
46 | { | ||
47 | int err = ME_ERRNO_SUCCESS; | ||
48 | me_subdevice_t *s; | ||
49 | |||
50 | PDEBUG("executed.\n"); | ||
51 | |||
52 | // Check subdevice index. | ||
53 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
54 | PERROR("Invalid subdevice.\n"); | ||
55 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
56 | } | ||
57 | // Enter device. | ||
58 | err = me_dlock_enter(&device->dlock, filep); | ||
59 | |||
60 | if (err) { | ||
61 | PERROR("Cannot enter device.\n"); | ||
62 | return err; | ||
63 | } | ||
64 | // Get subdevice instance. | ||
65 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
66 | |||
67 | if (s) { | ||
68 | // Call subdevice method. | ||
69 | err = s->me_subdevice_io_irq_start(s, | ||
70 | filep, | ||
71 | channel, | ||
72 | irq_source, | ||
73 | irq_edge, irq_arg, flags); | ||
74 | } else { | ||
75 | // Something really bad happened. | ||
76 | PERROR("Cannot get subdevice instance.\n"); | ||
77 | err = ME_ERRNO_INTERNAL; | ||
78 | } | ||
79 | |||
80 | // Exit device. | ||
81 | me_dlock_exit(&device->dlock, filep); | ||
82 | |||
83 | return err; | ||
84 | } | ||
85 | |||
86 | static int me_device_io_irq_wait(struct me_device *device, | ||
87 | struct file *filep, | ||
88 | int subdevice, | ||
89 | int channel, | ||
90 | int *irq_count, | ||
91 | int *value, int time_out, int flags) | ||
92 | { | ||
93 | int err = ME_ERRNO_SUCCESS; | ||
94 | me_subdevice_t *s; | ||
95 | |||
96 | PDEBUG("executed.\n"); | ||
97 | |||
98 | // Check subdevice index. | ||
99 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
100 | PERROR("Invalid subdevice.\n"); | ||
101 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
102 | } | ||
103 | // Enter device. | ||
104 | err = me_dlock_enter(&device->dlock, filep); | ||
105 | |||
106 | if (err) { | ||
107 | PERROR("Cannot enter device.\n"); | ||
108 | return err; | ||
109 | } | ||
110 | // Get subdevice instance. | ||
111 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
112 | |||
113 | if (s) { | ||
114 | // Call subdevice method. | ||
115 | err = s->me_subdevice_io_irq_wait(s, | ||
116 | filep, | ||
117 | channel, | ||
118 | irq_count, | ||
119 | value, time_out, flags); | ||
120 | } else { | ||
121 | // Something really bad happened. | ||
122 | PERROR("Cannot get subdevice instance.\n"); | ||
123 | err = ME_ERRNO_INTERNAL; | ||
124 | } | ||
125 | |||
126 | // Exit device. | ||
127 | me_dlock_exit(&device->dlock, filep); | ||
128 | |||
129 | return err; | ||
130 | } | ||
131 | |||
132 | static int me_device_io_irq_stop(struct me_device *device, | ||
133 | struct file *filep, | ||
134 | int subdevice, int channel, int flags) | ||
135 | { | ||
136 | int err = ME_ERRNO_SUCCESS; | ||
137 | me_subdevice_t *s; | ||
138 | |||
139 | PDEBUG("executed.\n"); | ||
140 | |||
141 | // Check subdevice index. | ||
142 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
143 | PERROR("Invalid subdevice.\n"); | ||
144 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
145 | } | ||
146 | // Enter device. | ||
147 | err = me_dlock_enter(&device->dlock, filep); | ||
148 | |||
149 | if (err) { | ||
150 | PERROR("Cannot enter device.\n"); | ||
151 | return err; | ||
152 | } | ||
153 | // Get subdevice instance. | ||
154 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
155 | |||
156 | if (s) { | ||
157 | // Call subdevice method. | ||
158 | err = s->me_subdevice_io_irq_stop(s, filep, channel, flags); | ||
159 | } else { | ||
160 | // Something really bad happened. | ||
161 | PERROR("Cannot get subdevice instance.\n"); | ||
162 | err = ME_ERRNO_INTERNAL; | ||
163 | } | ||
164 | |||
165 | // Exit device. | ||
166 | me_dlock_exit(&device->dlock, filep); | ||
167 | |||
168 | return err; | ||
169 | } | ||
170 | |||
171 | static int me_device_io_reset_device(struct me_device *device, | ||
172 | struct file *filep, int flags) | ||
173 | { | ||
174 | int err = ME_ERRNO_SUCCESS; | ||
175 | me_subdevice_t *s; | ||
176 | int i, n; | ||
177 | |||
178 | PDEBUG("executed.\n"); | ||
179 | |||
180 | /* Get the number of subdevices. */ | ||
181 | n = me_slist_get_number_subdevices(&device->slist); | ||
182 | |||
183 | // Enter device. | ||
184 | err = me_dlock_enter(&device->dlock, filep); | ||
185 | |||
186 | if (err) { | ||
187 | PERROR("Cannot enter device.\n"); | ||
188 | return err; | ||
189 | } | ||
190 | |||
191 | /* Reset every subdevice in list. */ | ||
192 | for (i = 0; i < n; i++) { | ||
193 | s = me_slist_get_subdevice(&device->slist, i); | ||
194 | err = s->me_subdevice_io_reset_subdevice(s, filep, flags); | ||
195 | |||
196 | if (err) { | ||
197 | PERROR("Cannot reset subdevice.\n"); | ||
198 | break; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | // Exit device. | ||
203 | me_dlock_exit(&device->dlock, filep); | ||
204 | |||
205 | return err; | ||
206 | } | ||
207 | |||
208 | static int me_device_io_reset_subdevice(struct me_device *device, | ||
209 | struct file *filep, | ||
210 | int subdevice, int flags) | ||
211 | { | ||
212 | int err = ME_ERRNO_SUCCESS; | ||
213 | me_subdevice_t *s; | ||
214 | |||
215 | PDEBUG("executed.\n"); | ||
216 | |||
217 | // Check subdevice index. | ||
218 | |||
219 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
220 | PERROR("Invalid subdevice.\n"); | ||
221 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
222 | } | ||
223 | // Enter device. | ||
224 | err = me_dlock_enter(&device->dlock, filep); | ||
225 | |||
226 | if (err) { | ||
227 | PERROR("Cannot enter device.\n"); | ||
228 | return err; | ||
229 | } | ||
230 | // Get subdevice instance. | ||
231 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
232 | |||
233 | if (s) { | ||
234 | // Call subdevice method. | ||
235 | err = s->me_subdevice_io_reset_subdevice(s, filep, flags); | ||
236 | } else { | ||
237 | // Something really bad happened. | ||
238 | PERROR("Cannot get subdevice instance.\n"); | ||
239 | err = ME_ERRNO_INTERNAL; | ||
240 | } | ||
241 | |||
242 | // Exit device. | ||
243 | me_dlock_exit(&device->dlock, filep); | ||
244 | |||
245 | return err; | ||
246 | } | ||
247 | |||
248 | static int me_device_io_single_config(struct me_device *device, | ||
249 | struct file *filep, | ||
250 | int subdevice, | ||
251 | int channel, | ||
252 | int single_config, | ||
253 | int ref, | ||
254 | int trig_chan, | ||
255 | int trig_type, int trig_edge, int flags) | ||
256 | { | ||
257 | int err = ME_ERRNO_SUCCESS; | ||
258 | me_subdevice_t *s; | ||
259 | |||
260 | PDEBUG("executed.\n"); | ||
261 | |||
262 | // Check subdevice index. | ||
263 | |||
264 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
265 | PERROR("Invalid subdevice.\n"); | ||
266 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
267 | } | ||
268 | // Enter device. | ||
269 | err = me_dlock_enter(&device->dlock, filep); | ||
270 | |||
271 | if (err) { | ||
272 | PERROR("Cannot enter device.\n"); | ||
273 | return err; | ||
274 | } | ||
275 | // Get subdevice instance. | ||
276 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
277 | |||
278 | if (s) { | ||
279 | // Call subdevice method. | ||
280 | err = s->me_subdevice_io_single_config(s, | ||
281 | filep, | ||
282 | channel, | ||
283 | single_config, | ||
284 | ref, | ||
285 | trig_chan, | ||
286 | trig_type, | ||
287 | trig_edge, flags); | ||
288 | } else { | ||
289 | // Something really bad happened. | ||
290 | PERROR("Cannot get subdevice instance.\n"); | ||
291 | err = ME_ERRNO_INTERNAL; | ||
292 | } | ||
293 | |||
294 | // Exit device. | ||
295 | me_dlock_exit(&device->dlock, filep); | ||
296 | |||
297 | return err; | ||
298 | } | ||
299 | |||
300 | static int me_device_io_single_read(struct me_device *device, | ||
301 | struct file *filep, | ||
302 | int subdevice, | ||
303 | int channel, | ||
304 | int *value, int time_out, int flags) | ||
305 | { | ||
306 | int err = ME_ERRNO_SUCCESS; | ||
307 | me_subdevice_t *s; | ||
308 | |||
309 | PDEBUG("executed.\n"); | ||
310 | |||
311 | // Check subdevice index. | ||
312 | |||
313 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
314 | PERROR("Invalid subdevice.\n"); | ||
315 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
316 | } | ||
317 | // Enter device. | ||
318 | err = me_dlock_enter(&device->dlock, filep); | ||
319 | |||
320 | if (err) { | ||
321 | PERROR("Cannot enter device.\n"); | ||
322 | return err; | ||
323 | } | ||
324 | // Get subdevice instance. | ||
325 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
326 | |||
327 | if (s) { | ||
328 | // Call subdevice method. | ||
329 | err = s->me_subdevice_io_single_read(s, | ||
330 | filep, | ||
331 | channel, | ||
332 | value, time_out, flags); | ||
333 | } else { | ||
334 | // Something really bad happened. | ||
335 | PERROR("Cannot get subdevice instance.\n"); | ||
336 | err = ME_ERRNO_INTERNAL; | ||
337 | } | ||
338 | |||
339 | // Exit device. | ||
340 | me_dlock_exit(&device->dlock, filep); | ||
341 | |||
342 | return err; | ||
343 | } | ||
344 | |||
345 | static int me_device_io_single_write(struct me_device *device, | ||
346 | struct file *filep, | ||
347 | int subdevice, | ||
348 | int channel, | ||
349 | int value, int time_out, int flags) | ||
350 | { | ||
351 | int err = ME_ERRNO_SUCCESS; | ||
352 | me_subdevice_t *s; | ||
353 | |||
354 | PDEBUG("executed.\n"); | ||
355 | |||
356 | // Check subdevice index. | ||
357 | |||
358 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
359 | PERROR("Invalid subdevice.\n"); | ||
360 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
361 | } | ||
362 | // Enter device. | ||
363 | err = me_dlock_enter(&device->dlock, filep); | ||
364 | |||
365 | if (err) { | ||
366 | PERROR("Cannot enter device.\n"); | ||
367 | return err; | ||
368 | } | ||
369 | // Get subdevice instance. | ||
370 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
371 | |||
372 | if (s) { | ||
373 | // Call subdevice method. | ||
374 | err = s->me_subdevice_io_single_write(s, | ||
375 | filep, | ||
376 | channel, | ||
377 | value, time_out, flags); | ||
378 | } else { | ||
379 | // Something really bad happened. | ||
380 | PERROR("Cannot get subdevice instance.\n"); | ||
381 | err = ME_ERRNO_INTERNAL; | ||
382 | } | ||
383 | |||
384 | // Exit device. | ||
385 | me_dlock_exit(&device->dlock, filep); | ||
386 | |||
387 | return err; | ||
388 | } | ||
389 | |||
390 | static int me_device_io_stream_config(struct me_device *device, | ||
391 | struct file *filep, | ||
392 | int subdevice, | ||
393 | meIOStreamConfig_t *config_list, | ||
394 | int count, | ||
395 | meIOStreamTrigger_t *trigger, | ||
396 | int fifo_irq_threshold, int flags) | ||
397 | { | ||
398 | int err = ME_ERRNO_SUCCESS; | ||
399 | me_subdevice_t *s; | ||
400 | |||
401 | PDEBUG("executed.\n"); | ||
402 | |||
403 | // Check subdevice index. | ||
404 | |||
405 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
406 | PERROR("Invalid subdevice.\n"); | ||
407 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
408 | } | ||
409 | // Enter device. | ||
410 | err = me_dlock_enter(&device->dlock, filep); | ||
411 | |||
412 | if (err) { | ||
413 | PERROR("Cannot enter device.\n"); | ||
414 | return err; | ||
415 | } | ||
416 | // Get subdevice instance. | ||
417 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
418 | |||
419 | if (s) { | ||
420 | // Call subdevice method. | ||
421 | err = s->me_subdevice_io_stream_config(s, | ||
422 | filep, | ||
423 | config_list, | ||
424 | count, | ||
425 | trigger, | ||
426 | fifo_irq_threshold, | ||
427 | flags); | ||
428 | } else { | ||
429 | // Something really bad happened. | ||
430 | PERROR("Cannot get subdevice instance.\n"); | ||
431 | err = ME_ERRNO_INTERNAL; | ||
432 | } | ||
433 | |||
434 | // Exit device. | ||
435 | me_dlock_exit(&device->dlock, filep); | ||
436 | |||
437 | return err; | ||
438 | } | ||
439 | |||
440 | static int me_device_io_stream_new_values(struct me_device *device, | ||
441 | struct file *filep, | ||
442 | int subdevice, | ||
443 | int time_out, int *count, int flags) | ||
444 | { | ||
445 | int err = ME_ERRNO_SUCCESS; | ||
446 | me_subdevice_t *s; | ||
447 | |||
448 | PDEBUG("executed.\n"); | ||
449 | |||
450 | // Check subdevice index. | ||
451 | |||
452 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
453 | PERROR("Invalid subdevice.\n"); | ||
454 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
455 | } | ||
456 | // Enter device. | ||
457 | err = me_dlock_enter(&device->dlock, filep); | ||
458 | |||
459 | if (err) { | ||
460 | PERROR("Cannot enter device.\n"); | ||
461 | return err; | ||
462 | } | ||
463 | // Get subdevice instance. | ||
464 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
465 | |||
466 | if (s) { | ||
467 | // Call subdevice method. | ||
468 | err = s->me_subdevice_io_stream_new_values(s, | ||
469 | filep, | ||
470 | time_out, | ||
471 | count, flags); | ||
472 | } else { | ||
473 | // Something really bad happened. | ||
474 | PERROR("Cannot get subdevice instance.\n"); | ||
475 | err = ME_ERRNO_INTERNAL; | ||
476 | } | ||
477 | |||
478 | // Exit device. | ||
479 | me_dlock_exit(&device->dlock, filep); | ||
480 | |||
481 | return err; | ||
482 | } | ||
483 | |||
484 | static int me_device_io_stream_read(struct me_device *device, | ||
485 | struct file *filep, | ||
486 | int subdevice, | ||
487 | int read_mode, | ||
488 | int *values, int *count, int flags) | ||
489 | { | ||
490 | int err = ME_ERRNO_SUCCESS; | ||
491 | me_subdevice_t *s; | ||
492 | |||
493 | PDEBUG("executed.\n"); | ||
494 | |||
495 | // Check subdevice index. | ||
496 | |||
497 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
498 | PERROR("Invalid subdevice.\n"); | ||
499 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
500 | } | ||
501 | // Enter device. | ||
502 | err = me_dlock_enter(&device->dlock, filep); | ||
503 | |||
504 | if (err) { | ||
505 | PERROR("Cannot enter device.\n"); | ||
506 | return err; | ||
507 | } | ||
508 | // Get subdevice instance. | ||
509 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
510 | |||
511 | if (s) { | ||
512 | // Call subdevice method. | ||
513 | err = s->me_subdevice_io_stream_read(s, | ||
514 | filep, | ||
515 | read_mode, | ||
516 | values, count, flags); | ||
517 | } else { | ||
518 | // Something really bad happened. | ||
519 | PERROR("Cannot get subdevice instance.\n"); | ||
520 | err = ME_ERRNO_INTERNAL; | ||
521 | } | ||
522 | |||
523 | // Exit device. | ||
524 | me_dlock_exit(&device->dlock, filep); | ||
525 | |||
526 | return err; | ||
527 | } | ||
528 | |||
529 | static int me_device_io_stream_start(struct me_device *device, | ||
530 | struct file *filep, | ||
531 | int subdevice, | ||
532 | int start_mode, int time_out, int flags) | ||
533 | { | ||
534 | int err = ME_ERRNO_SUCCESS; | ||
535 | me_subdevice_t *s; | ||
536 | |||
537 | PDEBUG("executed.\n"); | ||
538 | |||
539 | // Check subdevice index. | ||
540 | |||
541 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
542 | PERROR("Invalid subdevice.\n"); | ||
543 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
544 | } | ||
545 | // Enter device. | ||
546 | err = me_dlock_enter(&device->dlock, filep); | ||
547 | |||
548 | if (err) { | ||
549 | PERROR("Cannot enter device.\n"); | ||
550 | return err; | ||
551 | } | ||
552 | // Get subdevice instance. | ||
553 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
554 | |||
555 | if (s) { | ||
556 | // Call subdevice method. | ||
557 | err = s->me_subdevice_io_stream_start(s, | ||
558 | filep, | ||
559 | start_mode, | ||
560 | time_out, flags); | ||
561 | } else { | ||
562 | // Something really bad happened. | ||
563 | PERROR("Cannot get subdevice instance.\n"); | ||
564 | err = ME_ERRNO_INTERNAL; | ||
565 | } | ||
566 | |||
567 | // Exit device. | ||
568 | me_dlock_exit(&device->dlock, filep); | ||
569 | |||
570 | return err; | ||
571 | } | ||
572 | |||
573 | static int me_device_io_stream_status(struct me_device *device, | ||
574 | struct file *filep, | ||
575 | int subdevice, | ||
576 | int wait, | ||
577 | int *status, int *count, int flags) | ||
578 | { | ||
579 | int err = ME_ERRNO_SUCCESS; | ||
580 | me_subdevice_t *s; | ||
581 | |||
582 | PDEBUG("executed.\n"); | ||
583 | |||
584 | // Check subdevice index. | ||
585 | |||
586 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
587 | PERROR("Invalid subdevice.\n"); | ||
588 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
589 | } | ||
590 | // Enter device. | ||
591 | err = me_dlock_enter(&device->dlock, filep); | ||
592 | |||
593 | if (err) { | ||
594 | PERROR("Cannot enter device.\n"); | ||
595 | return err; | ||
596 | } | ||
597 | // Get subdevice instance. | ||
598 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
599 | |||
600 | if (s) { | ||
601 | // Call subdevice method. | ||
602 | err = s->me_subdevice_io_stream_status(s, | ||
603 | filep, | ||
604 | wait, | ||
605 | status, count, flags); | ||
606 | } else { | ||
607 | // Something really bad happened. | ||
608 | PERROR("Cannot get subdevice instance.\n"); | ||
609 | err = ME_ERRNO_INTERNAL; | ||
610 | } | ||
611 | |||
612 | // Exit device. | ||
613 | me_dlock_exit(&device->dlock, filep); | ||
614 | |||
615 | return err; | ||
616 | } | ||
617 | |||
618 | static int me_device_io_stream_stop(struct me_device *device, | ||
619 | struct file *filep, | ||
620 | int subdevice, int stop_mode, int flags) | ||
621 | { | ||
622 | int err = ME_ERRNO_SUCCESS; | ||
623 | me_subdevice_t *s; | ||
624 | |||
625 | PDEBUG("executed.\n"); | ||
626 | |||
627 | // Check subdevice index. | ||
628 | |||
629 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
630 | PERROR("Invalid subdevice.\n"); | ||
631 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
632 | } | ||
633 | // Enter device. | ||
634 | err = me_dlock_enter(&device->dlock, filep); | ||
635 | |||
636 | if (err) { | ||
637 | PERROR("Cannot enter device.\n"); | ||
638 | return err; | ||
639 | } | ||
640 | // Get subdevice instance. | ||
641 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
642 | |||
643 | if (s) { | ||
644 | // Call subdevice method. | ||
645 | err = s->me_subdevice_io_stream_stop(s, | ||
646 | filep, stop_mode, flags); | ||
647 | } else { | ||
648 | // Something really bad happened. | ||
649 | PERROR("Cannot get subdevice instance.\n"); | ||
650 | err = ME_ERRNO_INTERNAL; | ||
651 | } | ||
652 | |||
653 | // Exit device. | ||
654 | me_dlock_exit(&device->dlock, filep); | ||
655 | |||
656 | return err; | ||
657 | } | ||
658 | |||
659 | static int me_device_io_stream_write(struct me_device *device, | ||
660 | struct file *filep, | ||
661 | int subdevice, | ||
662 | int write_mode, | ||
663 | int *values, int *count, int flags) | ||
664 | { | ||
665 | int err = ME_ERRNO_SUCCESS; | ||
666 | me_subdevice_t *s; | ||
667 | |||
668 | PDEBUG("executed.\n"); | ||
669 | |||
670 | // Check subdevice index. | ||
671 | |||
672 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
673 | PERROR("Invalid subdevice.\n"); | ||
674 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
675 | } | ||
676 | // Enter device. | ||
677 | err = me_dlock_enter(&device->dlock, filep); | ||
678 | |||
679 | if (err) { | ||
680 | PERROR("Cannot enter device.\n"); | ||
681 | return err; | ||
682 | } | ||
683 | // Get subdevice instance. | ||
684 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
685 | |||
686 | if (s) { | ||
687 | // Call subdevice method. | ||
688 | err = s->me_subdevice_io_stream_write(s, | ||
689 | filep, | ||
690 | write_mode, | ||
691 | values, count, flags); | ||
692 | } else { | ||
693 | // Something really bad happened. | ||
694 | PERROR("Cannot get subdevice instance.\n"); | ||
695 | err = ME_ERRNO_INTERNAL; | ||
696 | } | ||
697 | |||
698 | // Exit device. | ||
699 | me_dlock_exit(&device->dlock, filep); | ||
700 | |||
701 | return err; | ||
702 | } | ||
703 | |||
704 | static int me_device_lock_device(struct me_device *device, | ||
705 | struct file *filep, int lock, int flags) | ||
706 | { | ||
707 | PDEBUG("executed.\n"); | ||
708 | |||
709 | return me_dlock_lock(&device->dlock, | ||
710 | filep, lock, flags, &device->slist); | ||
711 | } | ||
712 | |||
713 | static int me_device_lock_subdevice(struct me_device *device, | ||
714 | struct file *filep, | ||
715 | int subdevice, int lock, int flags) | ||
716 | { | ||
717 | int err = ME_ERRNO_SUCCESS; | ||
718 | me_subdevice_t *s; | ||
719 | |||
720 | PDEBUG("executed.\n"); | ||
721 | |||
722 | // Check subdevice index. | ||
723 | |||
724 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
725 | PERROR("Invalid subdevice.\n"); | ||
726 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
727 | } | ||
728 | // Enter device. | ||
729 | err = me_dlock_enter(&device->dlock, filep); | ||
730 | |||
731 | if (err) { | ||
732 | PERROR("Cannot enter device.\n"); | ||
733 | return err; | ||
734 | } | ||
735 | // Get subdevice instance. | ||
736 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
737 | |||
738 | if (s) { | ||
739 | // Call subdevice method. | ||
740 | err = s->me_subdevice_lock_subdevice(s, filep, lock, flags); | ||
741 | } else { | ||
742 | // Something really bad happened. | ||
743 | PERROR("Cannot get subdevice instance.\n"); | ||
744 | err = ME_ERRNO_INTERNAL; | ||
745 | } | ||
746 | |||
747 | // Exit device. | ||
748 | me_dlock_exit(&device->dlock, filep); | ||
749 | |||
750 | return err; | ||
751 | } | ||
752 | |||
753 | static int me_device_query_description_device(struct me_device *device, | ||
754 | char **description) | ||
755 | { | ||
756 | PDEBUG("executed.\n"); | ||
757 | *description = device->device_description; | ||
758 | return ME_ERRNO_SUCCESS; | ||
759 | } | ||
760 | |||
761 | static int me_device_query_info_device(struct me_device *device, | ||
762 | int *vendor_id, | ||
763 | int *device_id, | ||
764 | int *serial_no, | ||
765 | int *bus_type, | ||
766 | int *bus_no, | ||
767 | int *dev_no, int *func_no, int *plugged) | ||
768 | { | ||
769 | PDEBUG("executed.\n"); | ||
770 | |||
771 | if (device->bus_type == ME_BUS_TYPE_PCI) { | ||
772 | *vendor_id = device->info.pci.vendor_id; | ||
773 | *device_id = device->info.pci.device_id; | ||
774 | *serial_no = device->info.pci.serial_no; | ||
775 | *bus_type = ME_BUS_TYPE_PCI; | ||
776 | *bus_no = device->info.pci.pci_bus_no; | ||
777 | *dev_no = device->info.pci.pci_dev_no; | ||
778 | *func_no = device->info.pci.pci_func_no; | ||
779 | *plugged = ME_PLUGGED_IN; | ||
780 | } else { | ||
781 | *plugged = ME_PLUGGED_OUT; | ||
782 | } | ||
783 | return ME_ERRNO_SUCCESS; | ||
784 | } | ||
785 | |||
786 | static int me_device_query_name_device(struct me_device *device, char **name) | ||
787 | { | ||
788 | PDEBUG("executed.\n"); | ||
789 | *name = device->device_name; | ||
790 | return ME_ERRNO_SUCCESS; | ||
791 | } | ||
792 | |||
793 | static int me_device_query_name_device_driver(struct me_device *device, | ||
794 | char **name) | ||
795 | { | ||
796 | PDEBUG("executed.\n"); | ||
797 | *name = device->driver_name; | ||
798 | return ME_ERRNO_SUCCESS; | ||
799 | } | ||
800 | |||
801 | static int me_device_query_number_subdevices(struct me_device *device, | ||
802 | int *number) | ||
803 | { | ||
804 | PDEBUG("executed.\n"); | ||
805 | return me_slist_query_number_subdevices(&device->slist, number); | ||
806 | } | ||
807 | |||
808 | static int me_device_query_number_channels(struct me_device *device, | ||
809 | int subdevice, int *number) | ||
810 | { | ||
811 | int err = ME_ERRNO_SUCCESS; | ||
812 | me_subdevice_t *s; | ||
813 | |||
814 | PDEBUG("executed.\n"); | ||
815 | |||
816 | // Check subdevice index. | ||
817 | |||
818 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
819 | PERROR("Invalid subdevice.\n"); | ||
820 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
821 | } | ||
822 | // Get subdevice instance. | ||
823 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
824 | |||
825 | if (s) { | ||
826 | // Call subdevice method. | ||
827 | err = s->me_subdevice_query_number_channels(s, number); | ||
828 | } else { | ||
829 | // Something really bad happened. | ||
830 | PERROR("Cannot get subdevice instance.\n"); | ||
831 | err = ME_ERRNO_INTERNAL; | ||
832 | } | ||
833 | |||
834 | return err; | ||
835 | } | ||
836 | |||
837 | static int me_device_query_number_ranges(struct me_device *device, | ||
838 | int subdevice, int unit, int *count) | ||
839 | { | ||
840 | int err = ME_ERRNO_SUCCESS; | ||
841 | me_subdevice_t *s; | ||
842 | |||
843 | PDEBUG("executed.\n"); | ||
844 | |||
845 | // Check subdevice index. | ||
846 | |||
847 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
848 | PERROR("Invalid subdevice.\n"); | ||
849 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
850 | } | ||
851 | // Get subdevice instance. | ||
852 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
853 | |||
854 | if (s) { | ||
855 | // Call subdevice method. | ||
856 | err = s->me_subdevice_query_number_ranges(s, unit, count); | ||
857 | } else { | ||
858 | // Something really bad happened. | ||
859 | PERROR("Cannot get subdevice instance.\n"); | ||
860 | err = ME_ERRNO_INTERNAL; | ||
861 | } | ||
862 | |||
863 | return err; | ||
864 | } | ||
865 | |||
866 | static int me_device_query_range_by_min_max(struct me_device *device, | ||
867 | int subdevice, | ||
868 | int unit, | ||
869 | int *min, | ||
870 | int *max, int *maxdata, int *range) | ||
871 | { | ||
872 | int err = ME_ERRNO_SUCCESS; | ||
873 | me_subdevice_t *s; | ||
874 | |||
875 | PDEBUG("executed.\n"); | ||
876 | |||
877 | // Check subdevice index. | ||
878 | |||
879 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
880 | PERROR("Invalid subdevice.\n"); | ||
881 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
882 | } | ||
883 | // Get subdevice instance. | ||
884 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
885 | |||
886 | if (s) { | ||
887 | // Call subdevice method. | ||
888 | err = s->me_subdevice_query_range_by_min_max(s, | ||
889 | unit, | ||
890 | min, | ||
891 | max, | ||
892 | maxdata, range); | ||
893 | } else { | ||
894 | // Something really bad happened. | ||
895 | PERROR("Cannot get subdevice instance.\n"); | ||
896 | err = ME_ERRNO_INTERNAL; | ||
897 | } | ||
898 | |||
899 | return err; | ||
900 | } | ||
901 | |||
902 | static int me_device_query_range_info(struct me_device *device, | ||
903 | int subdevice, | ||
904 | int range, | ||
905 | int *unit, | ||
906 | int *min, int *max, int *maxdata) | ||
907 | { | ||
908 | int err = ME_ERRNO_SUCCESS; | ||
909 | me_subdevice_t *s; | ||
910 | |||
911 | PDEBUG("executed.\n"); | ||
912 | |||
913 | // Check subdevice index. | ||
914 | |||
915 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
916 | PERROR("Invalid subdevice.\n"); | ||
917 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
918 | } | ||
919 | // Get subdevice instance. | ||
920 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
921 | |||
922 | if (s) { | ||
923 | // Call subdevice method. | ||
924 | err = s->me_subdevice_query_range_info(s, | ||
925 | range, | ||
926 | unit, min, max, maxdata); | ||
927 | } else { | ||
928 | // Something really bad happened. | ||
929 | PERROR("Cannot get subdevice instance.\n"); | ||
930 | err = ME_ERRNO_INTERNAL; | ||
931 | } | ||
932 | |||
933 | return err; | ||
934 | } | ||
935 | |||
936 | static int me_device_query_subdevice_by_type(struct me_device *device, | ||
937 | int start_subdevice, | ||
938 | int type, | ||
939 | int subtype, int *subdevice) | ||
940 | { | ||
941 | PDEBUG("executed.\n"); | ||
942 | |||
943 | return me_slist_get_subdevice_by_type(&device->slist, | ||
944 | start_subdevice, | ||
945 | type, subtype, subdevice); | ||
946 | } | ||
947 | |||
948 | static int me_device_query_subdevice_type(struct me_device *device, | ||
949 | int subdevice, | ||
950 | int *type, int *subtype) | ||
951 | { | ||
952 | int err = ME_ERRNO_SUCCESS; | ||
953 | me_subdevice_t *s; | ||
954 | |||
955 | PDEBUG("executed.\n"); | ||
956 | |||
957 | // Check subdevice index. | ||
958 | |||
959 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
960 | PERROR("Invalid subdevice.\n"); | ||
961 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
962 | } | ||
963 | // Get subdevice instance. | ||
964 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
965 | |||
966 | if (s) { | ||
967 | // Call subdevice method. | ||
968 | err = s->me_subdevice_query_subdevice_type(s, type, subtype); | ||
969 | } else { | ||
970 | // Something really bad happened. | ||
971 | PERROR("Cannot get subdevice instance.\n"); | ||
972 | err = ME_ERRNO_INTERNAL; | ||
973 | } | ||
974 | |||
975 | return err; | ||
976 | } | ||
977 | |||
978 | static int me_device_query_subdevice_caps(struct me_device *device, | ||
979 | int subdevice, int *caps) | ||
980 | { | ||
981 | int err = ME_ERRNO_SUCCESS; | ||
982 | me_subdevice_t *s; | ||
983 | |||
984 | PDEBUG("executed.\n"); | ||
985 | |||
986 | // Check subdevice index. | ||
987 | |||
988 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
989 | PERROR("Invalid subdevice.\n"); | ||
990 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
991 | } | ||
992 | // Get subdevice instance. | ||
993 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
994 | |||
995 | if (s) { | ||
996 | // Call subdevice method. | ||
997 | err = s->me_subdevice_query_subdevice_caps(s, caps); | ||
998 | } else { | ||
999 | // Something really bad happened. | ||
1000 | PERROR("Cannot get subdevice instance.\n"); | ||
1001 | err = ME_ERRNO_INTERNAL; | ||
1002 | } | ||
1003 | |||
1004 | return err; | ||
1005 | } | ||
1006 | |||
1007 | static int me_device_query_subdevice_caps_args(struct me_device *device, | ||
1008 | int subdevice, | ||
1009 | int cap, int *args, int count) | ||
1010 | { | ||
1011 | int err = ME_ERRNO_SUCCESS; | ||
1012 | me_subdevice_t *s; | ||
1013 | |||
1014 | PDEBUG("executed.\n"); | ||
1015 | |||
1016 | // Check subdevice index. | ||
1017 | |||
1018 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
1019 | PERROR("Invalid subdevice.\n"); | ||
1020 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
1021 | } | ||
1022 | // Get subdevice instance. | ||
1023 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
1024 | |||
1025 | if (s) { | ||
1026 | // Call subdevice method. | ||
1027 | err = s->me_subdevice_query_subdevice_caps_args(s, | ||
1028 | cap, | ||
1029 | args, count); | ||
1030 | } else { | ||
1031 | // Something really bad happened. | ||
1032 | PERROR("Cannot get subdevice instance.\n"); | ||
1033 | err = ME_ERRNO_INTERNAL; | ||
1034 | } | ||
1035 | |||
1036 | return err; | ||
1037 | } | ||
1038 | |||
1039 | static int me_device_query_timer(struct me_device *device, | ||
1040 | int subdevice, | ||
1041 | int timer, | ||
1042 | int *base_frequency, | ||
1043 | uint64_t *min_ticks, uint64_t *max_ticks) | ||
1044 | { | ||
1045 | int err = ME_ERRNO_SUCCESS; | ||
1046 | me_subdevice_t *s; | ||
1047 | |||
1048 | PDEBUG("executed.\n"); | ||
1049 | |||
1050 | // Check subdevice index. | ||
1051 | |||
1052 | if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { | ||
1053 | PERROR("Invalid subdevice.\n"); | ||
1054 | return ME_ERRNO_INVALID_SUBDEVICE; | ||
1055 | } | ||
1056 | // Get subdevice instance. | ||
1057 | s = me_slist_get_subdevice(&device->slist, subdevice); | ||
1058 | |||
1059 | if (s) { | ||
1060 | // Call subdevice method. | ||
1061 | err = s->me_subdevice_query_timer(s, | ||
1062 | timer, | ||
1063 | base_frequency, | ||
1064 | min_ticks, max_ticks); | ||
1065 | } else { | ||
1066 | // Something really bad happened. | ||
1067 | PERROR("Cannot get subdevice instance.\n"); | ||
1068 | err = ME_ERRNO_INTERNAL; | ||
1069 | } | ||
1070 | |||
1071 | return err; | ||
1072 | } | ||
1073 | |||
1074 | static int me_device_query_version_device_driver(struct me_device *device, | ||
1075 | int *version) | ||
1076 | /** @todo Versions shold be read from driver. I must overwrite this function in each module. Here should be returned an error! | ||
1077 | */ | ||
1078 | { | ||
1079 | PDEBUG("executed.\n"); | ||
1080 | *version = ME_VERSION_DRIVER; | ||
1081 | return ME_ERRNO_SUCCESS; | ||
1082 | } | ||
1083 | |||
1084 | static int me_device_config_load(struct me_device *device, struct file *filep, | ||
1085 | me_cfg_device_entry_t *config) | ||
1086 | { | ||
1087 | PDEBUG("executed.\n"); | ||
1088 | return ME_ERRNO_SUCCESS; //If no need for config return success. | ||
1089 | // return ME_ERRNO_NOT_SUPPORTED; | ||
1090 | } | ||
1091 | |||
1092 | static void me_device_destructor(me_device_t *me_device) | ||
1093 | { | ||
1094 | PDEBUG("executed.\n"); | ||
1095 | me_device_deinit(me_device); | ||
1096 | kfree(me_device); | ||
1097 | } | ||
1098 | |||
1099 | /* //me_device_usb_init | ||
1100 | int me_device_usb_init(me_device_t *me_device, struct usb_interface *interface) | ||
1101 | { | ||
1102 | PDEBUG("executed.\n"); | ||
1103 | return -1; | ||
1104 | } | ||
1105 | */ | ||
1106 | |||
1107 | static int get_device_descriptions(uint16_t device_id, | ||
1108 | char **device_name, | ||
1109 | char **device_description, | ||
1110 | char **driver_name) | ||
1111 | /** @todo This is wrong concept! Static table has too strong limitations! | ||
1112 | * 'device_name' and 'driver_name' should be calculated from 'device_id' | ||
1113 | * 'device_description' should be read from device or moved to user space and handled by library! | ||
1114 | */ | ||
1115 | { | ||
1116 | PDEBUG("executed.\n"); | ||
1117 | |||
1118 | switch (device_id) { | ||
1119 | case PCI_DEVICE_ID_MEILHAUS_ME1000: | ||
1120 | case PCI_DEVICE_ID_MEILHAUS_ME1000_A: | ||
1121 | case PCI_DEVICE_ID_MEILHAUS_ME1000_B: | ||
1122 | *device_name = ME1000_NAME_DEVICE_ME1000; | ||
1123 | *device_description = ME1000_DESCRIPTION_DEVICE_ME1000; | ||
1124 | *driver_name = ME1000_NAME_DRIVER; | ||
1125 | break; | ||
1126 | |||
1127 | case PCI_DEVICE_ID_MEILHAUS_ME1400: | ||
1128 | *device_name = ME1400_NAME_DEVICE_ME1400; | ||
1129 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400; | ||
1130 | *driver_name = ME1400_NAME_DRIVER; | ||
1131 | break; | ||
1132 | |||
1133 | case PCI_DEVICE_ID_MEILHAUS_ME140A: | ||
1134 | *device_name = ME1400_NAME_DEVICE_ME1400A; | ||
1135 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400A; | ||
1136 | *driver_name = ME1400_NAME_DRIVER; | ||
1137 | break; | ||
1138 | |||
1139 | case PCI_DEVICE_ID_MEILHAUS_ME140B: | ||
1140 | *device_name = ME1400_NAME_DEVICE_ME1400B; | ||
1141 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400B; | ||
1142 | *driver_name = ME1400_NAME_DRIVER; | ||
1143 | break; | ||
1144 | |||
1145 | case PCI_DEVICE_ID_MEILHAUS_ME14E0: | ||
1146 | *device_name = ME1400_NAME_DEVICE_ME1400E; | ||
1147 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400E; | ||
1148 | *driver_name = ME1400_NAME_DRIVER; | ||
1149 | break; | ||
1150 | |||
1151 | case PCI_DEVICE_ID_MEILHAUS_ME14EA: | ||
1152 | *device_name = ME1400_NAME_DEVICE_ME1400EA; | ||
1153 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400EA; | ||
1154 | *driver_name = ME1400_NAME_DRIVER; | ||
1155 | break; | ||
1156 | |||
1157 | case PCI_DEVICE_ID_MEILHAUS_ME14EB: | ||
1158 | *device_name = ME1400_NAME_DEVICE_ME1400EB; | ||
1159 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400EB; | ||
1160 | *driver_name = ME1400_NAME_DRIVER; | ||
1161 | break; | ||
1162 | |||
1163 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
1164 | *device_name = ME1400_NAME_DEVICE_ME1400C; | ||
1165 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400C; | ||
1166 | *driver_name = ME1400_NAME_DRIVER; | ||
1167 | break; | ||
1168 | |||
1169 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
1170 | *device_name = ME1400_NAME_DEVICE_ME1400D; | ||
1171 | *device_description = ME1400_DESCRIPTION_DEVICE_ME1400D; | ||
1172 | *driver_name = ME1400_NAME_DRIVER; | ||
1173 | break; | ||
1174 | |||
1175 | case PCI_DEVICE_ID_MEILHAUS_ME1600_4U: | ||
1176 | *device_name = ME1600_NAME_DEVICE_ME16004U; | ||
1177 | *device_description = ME1600_DESCRIPTION_DEVICE_ME16004U; | ||
1178 | *driver_name = ME1600_NAME_DRIVER; | ||
1179 | break; | ||
1180 | |||
1181 | case PCI_DEVICE_ID_MEILHAUS_ME1600_8U: | ||
1182 | *device_name = ME1600_NAME_DEVICE_ME16008U; | ||
1183 | *device_description = ME1600_DESCRIPTION_DEVICE_ME16008U; | ||
1184 | *driver_name = ME1600_NAME_DRIVER; | ||
1185 | break; | ||
1186 | |||
1187 | case PCI_DEVICE_ID_MEILHAUS_ME1600_12U: | ||
1188 | *device_name = ME1600_NAME_DEVICE_ME160012U; | ||
1189 | *device_description = ME1600_DESCRIPTION_DEVICE_ME160012U; | ||
1190 | *driver_name = ME1600_NAME_DRIVER; | ||
1191 | break; | ||
1192 | |||
1193 | case PCI_DEVICE_ID_MEILHAUS_ME1600_16U: | ||
1194 | *device_name = ME1600_NAME_DEVICE_ME160016U; | ||
1195 | *device_description = ME1600_DESCRIPTION_DEVICE_ME160016U; | ||
1196 | *driver_name = ME1600_NAME_DRIVER; | ||
1197 | break; | ||
1198 | |||
1199 | case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I: | ||
1200 | *device_name = ME1600_NAME_DEVICE_ME160016U8I; | ||
1201 | *device_description = ME1600_DESCRIPTION_DEVICE_ME160016U8I; | ||
1202 | *driver_name = ME1600_NAME_DRIVER; | ||
1203 | break; | ||
1204 | |||
1205 | case PCI_DEVICE_ID_MEILHAUS_ME4610: | ||
1206 | *device_name = ME4600_NAME_DEVICE_ME4610; | ||
1207 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4610; | ||
1208 | *driver_name = ME4600_NAME_DRIVER; | ||
1209 | break; | ||
1210 | |||
1211 | case PCI_DEVICE_ID_MEILHAUS_ME4650: | ||
1212 | *device_name = ME4600_NAME_DEVICE_ME4650; | ||
1213 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4650; | ||
1214 | *driver_name = ME4600_NAME_DRIVER; | ||
1215 | break; | ||
1216 | |||
1217 | case PCI_DEVICE_ID_MEILHAUS_ME4660: | ||
1218 | *device_name = ME4600_NAME_DEVICE_ME4660; | ||
1219 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4660; | ||
1220 | *driver_name = ME4600_NAME_DRIVER; | ||
1221 | break; | ||
1222 | |||
1223 | case PCI_DEVICE_ID_MEILHAUS_ME4660I: | ||
1224 | *device_name = ME4600_NAME_DEVICE_ME4660I; | ||
1225 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4660I; | ||
1226 | *driver_name = ME4600_NAME_DRIVER; | ||
1227 | break; | ||
1228 | |||
1229 | case PCI_DEVICE_ID_MEILHAUS_ME4660S: | ||
1230 | *device_name = ME4600_NAME_DEVICE_ME4660S; | ||
1231 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4660S; | ||
1232 | *driver_name = ME4600_NAME_DRIVER; | ||
1233 | break; | ||
1234 | |||
1235 | case PCI_DEVICE_ID_MEILHAUS_ME4660IS: | ||
1236 | *device_name = ME4600_NAME_DEVICE_ME4660IS; | ||
1237 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4660IS; | ||
1238 | *driver_name = ME4600_NAME_DRIVER; | ||
1239 | break; | ||
1240 | |||
1241 | case PCI_DEVICE_ID_MEILHAUS_ME4670: | ||
1242 | *device_name = ME4600_NAME_DEVICE_ME4670; | ||
1243 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4670; | ||
1244 | *driver_name = ME4600_NAME_DRIVER; | ||
1245 | break; | ||
1246 | |||
1247 | case PCI_DEVICE_ID_MEILHAUS_ME4670I: | ||
1248 | *device_name = ME4600_NAME_DEVICE_ME4670I; | ||
1249 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4670I; | ||
1250 | *driver_name = ME4600_NAME_DRIVER; | ||
1251 | break; | ||
1252 | |||
1253 | case PCI_DEVICE_ID_MEILHAUS_ME4670S: | ||
1254 | *device_name = ME4600_NAME_DEVICE_ME4670S; | ||
1255 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4670S; | ||
1256 | *driver_name = ME4600_NAME_DRIVER; | ||
1257 | break; | ||
1258 | |||
1259 | case PCI_DEVICE_ID_MEILHAUS_ME4670IS: | ||
1260 | *device_name = ME4600_NAME_DEVICE_ME4670IS; | ||
1261 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4670IS; | ||
1262 | *driver_name = ME4600_NAME_DRIVER; | ||
1263 | break; | ||
1264 | |||
1265 | case PCI_DEVICE_ID_MEILHAUS_ME4680: | ||
1266 | *device_name = ME4600_NAME_DEVICE_ME4680; | ||
1267 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4680; | ||
1268 | *driver_name = ME4600_NAME_DRIVER; | ||
1269 | break; | ||
1270 | |||
1271 | case PCI_DEVICE_ID_MEILHAUS_ME4680I: | ||
1272 | *device_name = ME4600_NAME_DEVICE_ME4680I; | ||
1273 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4680I; | ||
1274 | *driver_name = ME4600_NAME_DRIVER; | ||
1275 | break; | ||
1276 | |||
1277 | case PCI_DEVICE_ID_MEILHAUS_ME4680S: | ||
1278 | *device_name = ME4600_NAME_DEVICE_ME4680S; | ||
1279 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4680S; | ||
1280 | *driver_name = ME4600_NAME_DRIVER; | ||
1281 | break; | ||
1282 | |||
1283 | case PCI_DEVICE_ID_MEILHAUS_ME4680IS: | ||
1284 | *device_name = ME4600_NAME_DEVICE_ME4680IS; | ||
1285 | *device_description = ME4600_DESCRIPTION_DEVICE_ME4680IS; | ||
1286 | *driver_name = ME4600_NAME_DRIVER; | ||
1287 | break; | ||
1288 | |||
1289 | case PCI_DEVICE_ID_MEILHAUS_ME6004: | ||
1290 | *device_name = ME6000_NAME_DEVICE_ME60004; | ||
1291 | *device_description = ME6000_DESCRIPTION_DEVICE_ME60004; | ||
1292 | *driver_name = ME6000_NAME_DRIVER; | ||
1293 | break; | ||
1294 | |||
1295 | case PCI_DEVICE_ID_MEILHAUS_ME6008: | ||
1296 | *device_name = ME6000_NAME_DEVICE_ME60008; | ||
1297 | *device_description = ME6000_DESCRIPTION_DEVICE_ME60008; | ||
1298 | *driver_name = ME6000_NAME_DRIVER; | ||
1299 | break; | ||
1300 | |||
1301 | case PCI_DEVICE_ID_MEILHAUS_ME600F: | ||
1302 | *device_name = ME6000_NAME_DEVICE_ME600016; | ||
1303 | *device_description = ME6000_DESCRIPTION_DEVICE_ME600016; | ||
1304 | *driver_name = ME6000_NAME_DRIVER; | ||
1305 | break; | ||
1306 | |||
1307 | case PCI_DEVICE_ID_MEILHAUS_ME6014: | ||
1308 | *device_name = ME6000_NAME_DEVICE_ME6000I4; | ||
1309 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I4; | ||
1310 | *driver_name = ME6000_NAME_DRIVER; | ||
1311 | break; | ||
1312 | |||
1313 | case PCI_DEVICE_ID_MEILHAUS_ME6018: | ||
1314 | *device_name = ME6000_NAME_DEVICE_ME6000I8; | ||
1315 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I8; | ||
1316 | *driver_name = ME6000_NAME_DRIVER; | ||
1317 | break; | ||
1318 | |||
1319 | case PCI_DEVICE_ID_MEILHAUS_ME601F: | ||
1320 | *device_name = ME6000_NAME_DEVICE_ME6000I16; | ||
1321 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I16; | ||
1322 | *driver_name = ME6000_NAME_DRIVER; | ||
1323 | break; | ||
1324 | |||
1325 | case PCI_DEVICE_ID_MEILHAUS_ME6034: | ||
1326 | *device_name = ME6000_NAME_DEVICE_ME6000ISLE4; | ||
1327 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4; | ||
1328 | *driver_name = ME6000_NAME_DRIVER; | ||
1329 | break; | ||
1330 | |||
1331 | case PCI_DEVICE_ID_MEILHAUS_ME6038: | ||
1332 | *device_name = ME6000_NAME_DEVICE_ME6000ISLE8; | ||
1333 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8; | ||
1334 | *driver_name = ME6000_NAME_DRIVER; | ||
1335 | break; | ||
1336 | |||
1337 | case PCI_DEVICE_ID_MEILHAUS_ME603F: | ||
1338 | *device_name = ME6000_NAME_DEVICE_ME6000ISLE16; | ||
1339 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16; | ||
1340 | *driver_name = ME6000_NAME_DRIVER; | ||
1341 | break; | ||
1342 | |||
1343 | case PCI_DEVICE_ID_MEILHAUS_ME6104: | ||
1344 | *device_name = ME6000_NAME_DEVICE_ME61004; | ||
1345 | *device_description = ME6000_DESCRIPTION_DEVICE_ME61004; | ||
1346 | *driver_name = ME6000_NAME_DRIVER; | ||
1347 | break; | ||
1348 | |||
1349 | case PCI_DEVICE_ID_MEILHAUS_ME6108: | ||
1350 | *device_name = ME6000_NAME_DEVICE_ME61008; | ||
1351 | *device_description = ME6000_DESCRIPTION_DEVICE_ME61008; | ||
1352 | *driver_name = ME6000_NAME_DRIVER; | ||
1353 | break; | ||
1354 | |||
1355 | case PCI_DEVICE_ID_MEILHAUS_ME610F: | ||
1356 | *device_name = ME6000_NAME_DEVICE_ME610016; | ||
1357 | *device_description = ME6000_DESCRIPTION_DEVICE_ME610016; | ||
1358 | *driver_name = ME6000_NAME_DRIVER; | ||
1359 | break; | ||
1360 | |||
1361 | case PCI_DEVICE_ID_MEILHAUS_ME6114: | ||
1362 | *device_name = ME6000_NAME_DEVICE_ME6100I4; | ||
1363 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I4; | ||
1364 | *driver_name = ME6000_NAME_DRIVER; | ||
1365 | break; | ||
1366 | |||
1367 | case PCI_DEVICE_ID_MEILHAUS_ME6118: | ||
1368 | *device_name = ME6000_NAME_DEVICE_ME6100I8; | ||
1369 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I8; | ||
1370 | *driver_name = ME6000_NAME_DRIVER; | ||
1371 | break; | ||
1372 | |||
1373 | case PCI_DEVICE_ID_MEILHAUS_ME611F: | ||
1374 | *device_name = ME6000_NAME_DEVICE_ME6100I16; | ||
1375 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I16; | ||
1376 | *driver_name = ME6000_NAME_DRIVER; | ||
1377 | break; | ||
1378 | |||
1379 | case PCI_DEVICE_ID_MEILHAUS_ME6134: | ||
1380 | *device_name = ME6000_NAME_DEVICE_ME6100ISLE4; | ||
1381 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4; | ||
1382 | *driver_name = ME6000_NAME_DRIVER; | ||
1383 | break; | ||
1384 | |||
1385 | case PCI_DEVICE_ID_MEILHAUS_ME6138: | ||
1386 | *device_name = ME6000_NAME_DEVICE_ME6100ISLE8; | ||
1387 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8; | ||
1388 | *driver_name = ME6000_NAME_DRIVER; | ||
1389 | break; | ||
1390 | |||
1391 | case PCI_DEVICE_ID_MEILHAUS_ME613F: | ||
1392 | *device_name = ME6000_NAME_DEVICE_ME6100ISLE16; | ||
1393 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16; | ||
1394 | *driver_name = ME6000_NAME_DRIVER; | ||
1395 | break; | ||
1396 | |||
1397 | case PCI_DEVICE_ID_MEILHAUS_ME6044: | ||
1398 | *device_name = ME6000_NAME_DEVICE_ME60004DIO; | ||
1399 | *device_description = ME6000_DESCRIPTION_DEVICE_ME60004DIO; | ||
1400 | *driver_name = ME6000_NAME_DRIVER; | ||
1401 | break; | ||
1402 | |||
1403 | case PCI_DEVICE_ID_MEILHAUS_ME6048: | ||
1404 | *device_name = ME6000_NAME_DEVICE_ME60008DIO; | ||
1405 | *device_description = ME6000_DESCRIPTION_DEVICE_ME60008DIO; | ||
1406 | *driver_name = ME6000_NAME_DRIVER; | ||
1407 | break; | ||
1408 | |||
1409 | case PCI_DEVICE_ID_MEILHAUS_ME604F: | ||
1410 | *device_name = ME6000_NAME_DEVICE_ME600016DIO; | ||
1411 | *device_description = ME6000_DESCRIPTION_DEVICE_ME600016DIO; | ||
1412 | *driver_name = ME6000_NAME_DRIVER; | ||
1413 | break; | ||
1414 | |||
1415 | case PCI_DEVICE_ID_MEILHAUS_ME6054: | ||
1416 | *device_name = ME6000_NAME_DEVICE_ME6000I4DIO; | ||
1417 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I4DIO; | ||
1418 | *driver_name = ME6000_NAME_DRIVER; | ||
1419 | break; | ||
1420 | |||
1421 | case PCI_DEVICE_ID_MEILHAUS_ME6058: | ||
1422 | *device_name = ME6000_NAME_DEVICE_ME6000I8DIO; | ||
1423 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I8DIO; | ||
1424 | *driver_name = ME6000_NAME_DRIVER; | ||
1425 | break; | ||
1426 | |||
1427 | case PCI_DEVICE_ID_MEILHAUS_ME605F: | ||
1428 | *device_name = ME6000_NAME_DEVICE_ME6000I16DIO; | ||
1429 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I16DIO; | ||
1430 | *driver_name = ME6000_NAME_DRIVER; | ||
1431 | break; | ||
1432 | |||
1433 | case PCI_DEVICE_ID_MEILHAUS_ME6074: | ||
1434 | *device_name = ME6000_NAME_DEVICE_ME6000ISLE4DIO; | ||
1435 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO; | ||
1436 | *driver_name = ME6000_NAME_DRIVER; | ||
1437 | break; | ||
1438 | |||
1439 | case PCI_DEVICE_ID_MEILHAUS_ME6078: | ||
1440 | *device_name = ME6000_NAME_DEVICE_ME6000ISLE8DIO; | ||
1441 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO; | ||
1442 | *driver_name = ME6000_NAME_DRIVER; | ||
1443 | break; | ||
1444 | |||
1445 | case PCI_DEVICE_ID_MEILHAUS_ME607F: | ||
1446 | *device_name = ME6000_NAME_DEVICE_ME6000ISLE16DIO; | ||
1447 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO; | ||
1448 | *driver_name = ME6000_NAME_DRIVER; | ||
1449 | break; | ||
1450 | |||
1451 | case PCI_DEVICE_ID_MEILHAUS_ME6144: | ||
1452 | *device_name = ME6000_NAME_DEVICE_ME61004DIO; | ||
1453 | *device_description = ME6000_DESCRIPTION_DEVICE_ME61004DIO; | ||
1454 | *driver_name = ME6000_NAME_DRIVER; | ||
1455 | break; | ||
1456 | |||
1457 | case PCI_DEVICE_ID_MEILHAUS_ME6148: | ||
1458 | *device_name = ME6000_NAME_DEVICE_ME61008DIO; | ||
1459 | *device_description = ME6000_DESCRIPTION_DEVICE_ME61008DIO; | ||
1460 | *driver_name = ME6000_NAME_DRIVER; | ||
1461 | break; | ||
1462 | |||
1463 | case PCI_DEVICE_ID_MEILHAUS_ME614F: | ||
1464 | *device_name = ME6000_NAME_DEVICE_ME610016DIO; | ||
1465 | *device_description = ME6000_DESCRIPTION_DEVICE_ME610016DIO; | ||
1466 | *driver_name = ME6000_NAME_DRIVER; | ||
1467 | break; | ||
1468 | |||
1469 | case PCI_DEVICE_ID_MEILHAUS_ME6154: | ||
1470 | *device_name = ME6000_NAME_DEVICE_ME6100I4DIO; | ||
1471 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I4DIO; | ||
1472 | *driver_name = ME6000_NAME_DRIVER; | ||
1473 | break; | ||
1474 | |||
1475 | case PCI_DEVICE_ID_MEILHAUS_ME6158: | ||
1476 | *device_name = ME6000_NAME_DEVICE_ME6100I8DIO; | ||
1477 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I8DIO; | ||
1478 | *driver_name = ME6000_NAME_DRIVER; | ||
1479 | break; | ||
1480 | |||
1481 | case PCI_DEVICE_ID_MEILHAUS_ME615F: | ||
1482 | *device_name = ME6000_NAME_DEVICE_ME6100I16DIO; | ||
1483 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I16DIO; | ||
1484 | *driver_name = ME6000_NAME_DRIVER; | ||
1485 | break; | ||
1486 | |||
1487 | case PCI_DEVICE_ID_MEILHAUS_ME6174: | ||
1488 | *device_name = ME6000_NAME_DEVICE_ME6100ISLE4DIO; | ||
1489 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO; | ||
1490 | *driver_name = ME6000_NAME_DRIVER; | ||
1491 | break; | ||
1492 | |||
1493 | case PCI_DEVICE_ID_MEILHAUS_ME6178: | ||
1494 | *device_name = ME6000_NAME_DEVICE_ME6100ISLE8DIO; | ||
1495 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO; | ||
1496 | *driver_name = ME6000_NAME_DRIVER; | ||
1497 | break; | ||
1498 | |||
1499 | case PCI_DEVICE_ID_MEILHAUS_ME617F: | ||
1500 | *device_name = ME6000_NAME_DEVICE_ME6100ISLE16DIO; | ||
1501 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO; | ||
1502 | *driver_name = ME6000_NAME_DRIVER; | ||
1503 | break; | ||
1504 | |||
1505 | case PCI_DEVICE_ID_MEILHAUS_ME6259: | ||
1506 | *device_name = ME6000_NAME_DEVICE_ME6200I9DIO; | ||
1507 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6200I9DIO; | ||
1508 | *driver_name = ME6000_NAME_DRIVER; | ||
1509 | break; | ||
1510 | |||
1511 | case PCI_DEVICE_ID_MEILHAUS_ME6359: | ||
1512 | *device_name = ME6000_NAME_DEVICE_ME6300I9DIO; | ||
1513 | *device_description = ME6000_DESCRIPTION_DEVICE_ME6300I9DIO; | ||
1514 | *driver_name = ME6000_NAME_DRIVER; | ||
1515 | break; | ||
1516 | |||
1517 | case PCI_DEVICE_ID_MEILHAUS_ME0630: | ||
1518 | *device_name = ME0600_NAME_DEVICE_ME0630; | ||
1519 | *device_description = ME0600_DESCRIPTION_DEVICE_ME0630; | ||
1520 | *driver_name = ME0600_NAME_DRIVER; | ||
1521 | break; | ||
1522 | |||
1523 | case PCI_DEVICE_ID_MEILHAUS_ME8100_A: | ||
1524 | *device_name = ME8100_NAME_DEVICE_ME8100A; | ||
1525 | *device_description = ME8100_DESCRIPTION_DEVICE_ME8100A; | ||
1526 | *driver_name = ME8100_NAME_DRIVER; | ||
1527 | break; | ||
1528 | |||
1529 | case PCI_DEVICE_ID_MEILHAUS_ME8100_B: | ||
1530 | *device_name = ME8100_NAME_DEVICE_ME8100B; | ||
1531 | *device_description = ME8100_DESCRIPTION_DEVICE_ME8100B; | ||
1532 | *driver_name = ME8100_NAME_DRIVER; | ||
1533 | break; | ||
1534 | |||
1535 | case PCI_DEVICE_ID_MEILHAUS_ME8200_A: | ||
1536 | *device_name = ME8200_NAME_DEVICE_ME8200A; | ||
1537 | *device_description = ME8200_DESCRIPTION_DEVICE_ME8200A; | ||
1538 | *driver_name = ME8200_NAME_DRIVER; | ||
1539 | break; | ||
1540 | |||
1541 | case PCI_DEVICE_ID_MEILHAUS_ME8200_B: | ||
1542 | *device_name = ME8200_NAME_DEVICE_ME8200B; | ||
1543 | *device_description = ME8200_DESCRIPTION_DEVICE_ME8200B; | ||
1544 | *driver_name = ME8200_NAME_DRIVER; | ||
1545 | break; | ||
1546 | |||
1547 | case PCI_DEVICE_ID_MEILHAUS_ME0940: | ||
1548 | *device_name = ME0900_NAME_DEVICE_ME0940; | ||
1549 | *device_description = ME0900_DESCRIPTION_DEVICE_ME0940; | ||
1550 | *driver_name = ME0900_NAME_DRIVER; | ||
1551 | break; | ||
1552 | |||
1553 | case PCI_DEVICE_ID_MEILHAUS_ME0950: | ||
1554 | *device_name = ME0900_NAME_DEVICE_ME0950; | ||
1555 | *device_description = ME0900_DESCRIPTION_DEVICE_ME0950; | ||
1556 | *driver_name = ME0900_NAME_DRIVER; | ||
1557 | break; | ||
1558 | |||
1559 | case PCI_DEVICE_ID_MEILHAUS_ME0960: | ||
1560 | *device_name = ME0900_NAME_DEVICE_ME0960; | ||
1561 | *device_description = ME0900_DESCRIPTION_DEVICE_ME0960; | ||
1562 | *driver_name = ME0900_NAME_DRIVER; | ||
1563 | break; | ||
1564 | /* | ||
1565 | case USB_DEVICE_ID_MEPHISTO_S1: | ||
1566 | *device_name = MEPHISTO_S1_NAME_DEVICE; | ||
1567 | *device_description = MEPHISTO_S1_DESCRIPTION_DEVICE; | ||
1568 | *driver_name = MEPHISTO_S1_NAME_DRIVER; | ||
1569 | break; | ||
1570 | */ | ||
1571 | default: | ||
1572 | *device_name = EMPTY_NAME_DEVICE; | ||
1573 | *device_description = EMPTY_DESCRIPTION_DEVICE; | ||
1574 | *driver_name = EMPTY_NAME_DRIVER; | ||
1575 | |||
1576 | PERROR("Invalid device id.\n"); | ||
1577 | |||
1578 | return 1; | ||
1579 | } | ||
1580 | |||
1581 | return 0; | ||
1582 | } | ||
1583 | |||
1584 | int me_device_pci_init(me_device_t *me_device, struct pci_dev *pci_device) | ||
1585 | { | ||
1586 | int err; | ||
1587 | int i; | ||
1588 | |||
1589 | PDEBUG("executed.\n"); | ||
1590 | |||
1591 | // Initialize device list head. | ||
1592 | INIT_LIST_HEAD(&me_device->list); | ||
1593 | |||
1594 | // Initialize device description strings. | ||
1595 | err = get_device_descriptions(pci_device->device, | ||
1596 | &me_device->device_name, | ||
1597 | &me_device->device_description, | ||
1598 | &me_device->driver_name); | ||
1599 | |||
1600 | if (err) { | ||
1601 | PERROR("Cannot initialize device description strings.\n"); | ||
1602 | return 1; | ||
1603 | } | ||
1604 | // Enable the pci device. | ||
1605 | err = pci_enable_device(pci_device); | ||
1606 | |||
1607 | if (err < 0) { | ||
1608 | PERROR("Cannot enable PCI device.\n"); | ||
1609 | return 1; | ||
1610 | } | ||
1611 | // Request the PCI register regions. | ||
1612 | err = pci_request_regions(pci_device, me_device->device_name); | ||
1613 | |||
1614 | if (err < 0) { | ||
1615 | PERROR("Cannot request PCI regions.\n"); | ||
1616 | goto ERROR_0; | ||
1617 | } | ||
1618 | // The bus carrying the device is a PCI bus. | ||
1619 | me_device->bus_type = ME_BUS_TYPE_PCI; | ||
1620 | |||
1621 | // Store the PCI information for later usage. | ||
1622 | me_device->info.pci.pci_device = pci_device; | ||
1623 | |||
1624 | // Get PCI register bases and sizes. | ||
1625 | for (i = 0; i < 6; i++) { | ||
1626 | me_device->info.pci.reg_bases[i] = | ||
1627 | pci_resource_start(pci_device, i); | ||
1628 | me_device->info.pci.reg_sizes[i] = | ||
1629 | pci_resource_len(pci_device, i); | ||
1630 | } | ||
1631 | |||
1632 | // Get the PCI location. | ||
1633 | me_device->info.pci.pci_bus_no = pci_device->bus->number; | ||
1634 | me_device->info.pci.pci_dev_no = PCI_SLOT(pci_device->devfn); | ||
1635 | me_device->info.pci.pci_func_no = PCI_FUNC(pci_device->devfn); | ||
1636 | |||
1637 | // Get Meilhaus specific device information. | ||
1638 | me_device->info.pci.vendor_id = pci_device->vendor; | ||
1639 | me_device->info.pci.device_id = pci_device->device; | ||
1640 | pci_read_config_byte(pci_device, 0x08, | ||
1641 | &me_device->info.pci.hw_revision); | ||
1642 | pci_read_config_dword(pci_device, 0x2C, &me_device->info.pci.serial_no); | ||
1643 | |||
1644 | // Get the interrupt request number. | ||
1645 | me_device->irq = pci_device->irq; | ||
1646 | |||
1647 | // Initialize device lock instance. | ||
1648 | err = me_dlock_init(&me_device->dlock); | ||
1649 | |||
1650 | if (err) { | ||
1651 | PERROR("Cannot initialize device lock instance.\n"); | ||
1652 | goto ERROR_1; | ||
1653 | } | ||
1654 | // Initialize subdevice list instance. | ||
1655 | me_slist_init(&me_device->slist); | ||
1656 | |||
1657 | if (err) { | ||
1658 | PERROR("Cannot initialize subdevice list instance.\n"); | ||
1659 | goto ERROR_2; | ||
1660 | } | ||
1661 | // Initialize method pointers. | ||
1662 | me_device->me_device_io_irq_start = me_device_io_irq_start; | ||
1663 | me_device->me_device_io_irq_wait = me_device_io_irq_wait; | ||
1664 | me_device->me_device_io_irq_stop = me_device_io_irq_stop; | ||
1665 | me_device->me_device_io_reset_device = me_device_io_reset_device; | ||
1666 | me_device->me_device_io_reset_subdevice = me_device_io_reset_subdevice; | ||
1667 | me_device->me_device_io_single_config = me_device_io_single_config; | ||
1668 | me_device->me_device_io_single_read = me_device_io_single_read; | ||
1669 | me_device->me_device_io_single_write = me_device_io_single_write; | ||
1670 | me_device->me_device_io_stream_config = me_device_io_stream_config; | ||
1671 | me_device->me_device_io_stream_new_values = | ||
1672 | me_device_io_stream_new_values; | ||
1673 | me_device->me_device_io_stream_read = me_device_io_stream_read; | ||
1674 | me_device->me_device_io_stream_start = me_device_io_stream_start; | ||
1675 | me_device->me_device_io_stream_status = me_device_io_stream_status; | ||
1676 | me_device->me_device_io_stream_stop = me_device_io_stream_stop; | ||
1677 | me_device->me_device_io_stream_write = me_device_io_stream_write; | ||
1678 | me_device->me_device_lock_device = me_device_lock_device; | ||
1679 | me_device->me_device_lock_subdevice = me_device_lock_subdevice; | ||
1680 | me_device->me_device_query_description_device = | ||
1681 | me_device_query_description_device; | ||
1682 | me_device->me_device_query_info_device = me_device_query_info_device; | ||
1683 | me_device->me_device_query_name_device = me_device_query_name_device; | ||
1684 | me_device->me_device_query_name_device_driver = | ||
1685 | me_device_query_name_device_driver; | ||
1686 | me_device->me_device_query_number_subdevices = | ||
1687 | me_device_query_number_subdevices; | ||
1688 | me_device->me_device_query_number_channels = | ||
1689 | me_device_query_number_channels; | ||
1690 | me_device->me_device_query_number_ranges = | ||
1691 | me_device_query_number_ranges; | ||
1692 | me_device->me_device_query_range_by_min_max = | ||
1693 | me_device_query_range_by_min_max; | ||
1694 | me_device->me_device_query_range_info = me_device_query_range_info; | ||
1695 | me_device->me_device_query_subdevice_by_type = | ||
1696 | me_device_query_subdevice_by_type; | ||
1697 | me_device->me_device_query_subdevice_type = | ||
1698 | me_device_query_subdevice_type; | ||
1699 | me_device->me_device_query_subdevice_caps = | ||
1700 | me_device_query_subdevice_caps; | ||
1701 | me_device->me_device_query_subdevice_caps_args = | ||
1702 | me_device_query_subdevice_caps_args; | ||
1703 | me_device->me_device_query_timer = me_device_query_timer; | ||
1704 | me_device->me_device_query_version_device_driver = | ||
1705 | me_device_query_version_device_driver; | ||
1706 | me_device->me_device_config_load = me_device_config_load; | ||
1707 | me_device->me_device_destructor = me_device_destructor; | ||
1708 | |||
1709 | return 0; | ||
1710 | |||
1711 | ERROR_0: | ||
1712 | me_dlock_deinit(&me_device->dlock); | ||
1713 | |||
1714 | ERROR_1: | ||
1715 | pci_release_regions(pci_device); | ||
1716 | |||
1717 | ERROR_2: | ||
1718 | pci_disable_device(pci_device); | ||
1719 | |||
1720 | return 1; | ||
1721 | } | ||
1722 | |||
1723 | void me_device_deinit(me_device_t *me_device) | ||
1724 | { | ||
1725 | PDEBUG("executed.\n"); | ||
1726 | |||
1727 | me_slist_deinit(&me_device->slist); | ||
1728 | me_dlock_deinit(&me_device->dlock); | ||
1729 | |||
1730 | if (me_device->bus_type == ME_BUS_TYPE_PCI) { | ||
1731 | pci_release_regions(me_device->info.pci.pci_device); | ||
1732 | pci_disable_device(me_device->info.pci.pci_device); | ||
1733 | } | ||
1734 | /* | ||
1735 | else | ||
1736 | { | ||
1737 | // Must be an USB device. | ||
1738 | } | ||
1739 | */ | ||
1740 | } | ||
diff --git a/drivers/staging/meilhaus/medevice.h b/drivers/staging/meilhaus/medevice.h deleted file mode 100644 index 25da82883e1f..000000000000 --- a/drivers/staging/meilhaus/medevice.h +++ /dev/null | |||
@@ -1,304 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : medevice.h | ||
5 | * Author : GG (Guenter Gebhardt) <support@meilhaus.de> | ||
6 | */ | ||
7 | |||
8 | #ifndef _MEDEVICE_H_ | ||
9 | #define _MEDEVICE_H_ | ||
10 | |||
11 | #ifndef KBUILD_MODNAME | ||
12 | # define KBUILD_MODNAME KBUILD_STR(memain) | ||
13 | #endif | ||
14 | |||
15 | #include <linux/pci.h> | ||
16 | //#include <linux/usb.h> | ||
17 | #include <linux/fs.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | |||
20 | #include "metypes.h" | ||
21 | #include "meslist.h" | ||
22 | #include "medlock.h" | ||
23 | |||
24 | #ifdef __KERNEL__ | ||
25 | |||
26 | /** | ||
27 | * @brief Defines a pointer type to a PCI constructor function. | ||
28 | */ | ||
29 | typedef struct me_device *(*me_pci_constructor_t) (struct pci_dev *); | ||
30 | |||
31 | /** | ||
32 | * @brief Defines a pointer type to a ME-4000 PCI constructor function. | ||
33 | */ | ||
34 | #ifdef BOSCH | ||
35 | typedef struct me_device *(*me_bosch_constructor_t) (struct pci_dev *, | ||
36 | int me_bosch_fw); | ||
37 | #endif | ||
38 | |||
39 | /** | ||
40 | * @brief Defines a pointer type to a USB constructor function. | ||
41 | */ | ||
42 | //typedef struct me_device *(*me_usb_constructor_t)(struct usb_interface *); | ||
43 | |||
44 | /** | ||
45 | * @brief Defines a pointer type to the dummy constructor function. | ||
46 | */ | ||
47 | typedef struct me_device *(*me_dummy_constructor_t) (unsigned short vendor_id, | ||
48 | unsigned short device_id, | ||
49 | unsigned int serial_no, | ||
50 | int bus_type, | ||
51 | int bus_no, | ||
52 | int dev_no, int func_no); | ||
53 | |||
54 | //extern me_usb_constructor_t mephisto_s1_constructor __attribute__ ((weak)); | ||
55 | |||
56 | /** | ||
57 | * @brief Holds the PCI device information. | ||
58 | */ | ||
59 | typedef struct me_pci_info { | ||
60 | struct pci_dev *pci_device; /**< Kernel PCI device structure. */ | ||
61 | uint32_t reg_bases[6]; /**< The base adresses of the PCI bars. */ | ||
62 | uint32_t reg_sizes[6]; /**< The sizes of the PCI bars. */ | ||
63 | |||
64 | uint32_t pci_bus_no; /**< PCI bus number. */ | ||
65 | uint32_t pci_dev_no; /**< PCI device number. */ | ||
66 | uint32_t pci_func_no; /**< PCI function number. */ | ||
67 | |||
68 | uint16_t vendor_id; /**< Meilhaus PCI vendor id. */ | ||
69 | uint16_t device_id; /**< Meilhaus device id. */ | ||
70 | uint8_t hw_revision; /**< Hardware revision of the device. */ | ||
71 | uint32_t serial_no; /**< Serial number of the device. */ | ||
72 | } me_pci_info_t; | ||
73 | |||
74 | /** | ||
75 | * @brief Holds the USB device information. | ||
76 | */ | ||
77 | //typedef struct me_usb_info { | ||
78 | //} me_usb_info_t; | ||
79 | |||
80 | /** | ||
81 | * @brief The Meilhaus device base class structure. | ||
82 | */ | ||
83 | typedef struct me_device { | ||
84 | /* Attributes */ | ||
85 | struct list_head list; /**< Enables the device to be added to a dynamic list. */ | ||
86 | // int magic; /**< The magic number of the structure. */ | ||
87 | |||
88 | int bus_type; /**< The descriminator for the union. */ | ||
89 | union { | ||
90 | me_pci_info_t pci; /**< PCI specific device information. */ | ||
91 | // me_usb_info_t usb; /**< USB specific device information. */ | ||
92 | } info; /**< Holds the device information. */ | ||
93 | |||
94 | int irq; /**< The irq assigned to this device. */ | ||
95 | |||
96 | me_dlock_t dlock; /**< The device locking structure. */ | ||
97 | me_slist_t slist; /**< The container holding all subdevices belonging to this device. */ | ||
98 | |||
99 | char *device_name; /**< The name of the Meilhaus device. */ | ||
100 | char *device_description; /**< The description of the Meilhaus device. */ | ||
101 | char *driver_name; /**< The name of the device driver module supporting the device family. */ | ||
102 | |||
103 | /* Methods */ | ||
104 | int (*me_device_io_irq_start) (struct me_device * device, | ||
105 | struct file * filep, | ||
106 | int subdevice, | ||
107 | int channel, | ||
108 | int irq_source, | ||
109 | int irq_edge, int irq_arg, int flags); | ||
110 | |||
111 | int (*me_device_io_irq_wait) (struct me_device * device, | ||
112 | struct file * filep, | ||
113 | int subdevice, | ||
114 | int channel, | ||
115 | int *irq_count, | ||
116 | int *value, int time_out, int flags); | ||
117 | |||
118 | int (*me_device_io_irq_stop) (struct me_device * device, | ||
119 | struct file * filep, | ||
120 | int subdevice, int channel, int flags); | ||
121 | |||
122 | int (*me_device_io_reset_device) (struct me_device * device, | ||
123 | struct file * filep, int flags); | ||
124 | |||
125 | int (*me_device_io_reset_subdevice) (struct me_device * device, | ||
126 | struct file * filep, | ||
127 | int subdevice, int flags); | ||
128 | |||
129 | int (*me_device_io_single_config) (struct me_device * device, | ||
130 | struct file * filep, | ||
131 | int subdevice, | ||
132 | int channel, | ||
133 | int single_config, | ||
134 | int ref, | ||
135 | int trig_chan, | ||
136 | int trig_type, | ||
137 | int trig_edge, int flags); | ||
138 | |||
139 | int (*me_device_io_single_read) (struct me_device * device, | ||
140 | struct file * filep, | ||
141 | int subdevice, | ||
142 | int channel, | ||
143 | int *value, int time_out, int flags); | ||
144 | |||
145 | int (*me_device_io_single_write) (struct me_device * device, | ||
146 | struct file * filep, | ||
147 | int subdevice, | ||
148 | int channel, | ||
149 | int value, int time_out, int flags); | ||
150 | |||
151 | int (*me_device_io_stream_config) (struct me_device * device, | ||
152 | struct file * filep, | ||
153 | int subdevice, | ||
154 | meIOStreamConfig_t * config_list, | ||
155 | int count, | ||
156 | meIOStreamTrigger_t * trigger, | ||
157 | int fifo_irq_threshold, int flags); | ||
158 | |||
159 | int (*me_device_io_stream_new_values) (struct me_device * device, | ||
160 | struct file * filep, | ||
161 | int subdevice, | ||
162 | int time_out, | ||
163 | int *count, int flags); | ||
164 | |||
165 | int (*me_device_io_stream_read) (struct me_device * device, | ||
166 | struct file * filep, | ||
167 | int subdevice, | ||
168 | int read_mode, | ||
169 | int *values, int *count, int flags); | ||
170 | |||
171 | int (*me_device_io_stream_start) (struct me_device * device, | ||
172 | struct file * filep, | ||
173 | int subdevice, | ||
174 | int start_mode, | ||
175 | int time_out, int flags); | ||
176 | |||
177 | int (*me_device_io_stream_status) (struct me_device * device, | ||
178 | struct file * filep, | ||
179 | int subdevice, | ||
180 | int wait, | ||
181 | int *status, int *count, int flags); | ||
182 | |||
183 | int (*me_device_io_stream_stop) (struct me_device * device, | ||
184 | struct file * filep, | ||
185 | int subdevice, | ||
186 | int stop_mode, int flags); | ||
187 | |||
188 | int (*me_device_io_stream_write) (struct me_device * device, | ||
189 | struct file * filep, | ||
190 | int subdevice, | ||
191 | int write_mode, | ||
192 | int *values, int *count, int flags); | ||
193 | |||
194 | int (*me_device_lock_device) (struct me_device * device, | ||
195 | struct file * filep, int lock, int flags); | ||
196 | |||
197 | int (*me_device_lock_subdevice) (struct me_device * device, | ||
198 | struct file * filep, | ||
199 | int subdevice, int lock, int flags); | ||
200 | |||
201 | int (*me_device_query_description_device) (struct me_device * device, | ||
202 | char **description); | ||
203 | |||
204 | int (*me_device_query_info_device) (struct me_device * device, | ||
205 | int *vendor_id, | ||
206 | int *device_id, | ||
207 | int *serial_no, | ||
208 | int *bus_type, | ||
209 | int *bus_no, | ||
210 | int *dev_no, | ||
211 | int *func_no, int *plugged); | ||
212 | |||
213 | int (*me_device_query_name_device) (struct me_device * device, | ||
214 | char **name); | ||
215 | |||
216 | int (*me_device_query_name_device_driver) (struct me_device * device, | ||
217 | char **name); | ||
218 | |||
219 | int (*me_device_query_number_subdevices) (struct me_device * device, | ||
220 | int *number); | ||
221 | |||
222 | int (*me_device_query_number_channels) (struct me_device * device, | ||
223 | int subdevice, int *number); | ||
224 | |||
225 | int (*me_device_query_number_ranges) (struct me_device * device, | ||
226 | int subdevice, | ||
227 | int unit, int *count); | ||
228 | |||
229 | int (*me_device_query_range_by_min_max) (struct me_device * device, | ||
230 | int subdevice, | ||
231 | int unit, | ||
232 | int *min, | ||
233 | int *max, | ||
234 | int *maxdata, int *range); | ||
235 | |||
236 | int (*me_device_query_range_info) (struct me_device * device, | ||
237 | int subdevice, | ||
238 | int range, | ||
239 | int *unit, | ||
240 | int *min, int *max, int *maxdata); | ||
241 | |||
242 | int (*me_device_query_subdevice_by_type) (struct me_device * device, | ||
243 | int start_subdevice, | ||
244 | int type, | ||
245 | int subtype, int *subdevice); | ||
246 | |||
247 | int (*me_device_query_subdevice_type) (struct me_device * device, | ||
248 | int subdevice, | ||
249 | int *type, int *subtype); | ||
250 | |||
251 | int (*me_device_query_subdevice_caps) (struct me_device * device, | ||
252 | int subdevice, int *caps); | ||
253 | |||
254 | int (*me_device_query_subdevice_caps_args) (struct me_device * device, | ||
255 | int subdevice, | ||
256 | int cap, | ||
257 | int *args, int count); | ||
258 | |||
259 | int (*me_device_query_timer) (struct me_device * device, | ||
260 | int subdevice, | ||
261 | int timer, | ||
262 | int *base_frequency, | ||
263 | uint64_t * min_ticks, | ||
264 | uint64_t * max_ticks); | ||
265 | |||
266 | int (*me_device_query_version_device_driver) (struct me_device * device, | ||
267 | int *version); | ||
268 | |||
269 | int (*me_device_config_load) (struct me_device * device, | ||
270 | struct file * filep, | ||
271 | me_cfg_device_entry_t * config); | ||
272 | |||
273 | void (*me_device_destructor) (struct me_device * device); | ||
274 | } me_device_t; | ||
275 | |||
276 | /** | ||
277 | * @brief Initializes a PCI device base class structure. | ||
278 | * | ||
279 | * @param pci_device The PCI device context as handed over by kernel. | ||
280 | * | ||
281 | * @return 0 on success. | ||
282 | */ | ||
283 | int me_device_pci_init(me_device_t * me_device, struct pci_dev *pci_device); | ||
284 | |||
285 | /** | ||
286 | * @brief Initializes a USB device base class structure. | ||
287 | * | ||
288 | * @param usb_interface The USB device interface as handed over by kernel. | ||
289 | * | ||
290 | * @return 0 on success. | ||
291 | */ | ||
292 | //int me_device_usb_init(me_device_t *me_device, struct usb_interface *interface); | ||
293 | |||
294 | /** | ||
295 | * @brief Deinitializes a device base class structure and frees any previously | ||
296 | * requested resources related with this structure. It also frees any subdevice | ||
297 | * instance hold by the subdevice list. | ||
298 | * | ||
299 | * @param me_device The device class to deinitialize. | ||
300 | */ | ||
301 | void me_device_deinit(me_device_t * me_device); | ||
302 | |||
303 | #endif | ||
304 | #endif | ||
diff --git a/drivers/staging/meilhaus/medlist.c b/drivers/staging/meilhaus/medlist.c deleted file mode 100644 index b6a4065d2da1..000000000000 --- a/drivers/staging/meilhaus/medlist.c +++ /dev/null | |||
@@ -1,127 +0,0 @@ | |||
1 | /** | ||
2 | * @file me_dlist.c | ||
3 | * | ||
4 | * @brief Implements the device list class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include "meerror.h" | ||
28 | #include "medefines.h" | ||
29 | |||
30 | #include "medlist.h" | ||
31 | #include "medebug.h" | ||
32 | |||
33 | int me_dlist_query_number_devices(struct me_dlist *dlist, int *number) | ||
34 | { | ||
35 | PDEBUG_LOCKS("called.\n"); | ||
36 | *number = dlist->n; | ||
37 | return ME_ERRNO_SUCCESS; | ||
38 | } | ||
39 | |||
40 | unsigned int me_dlist_get_number_devices(struct me_dlist *dlist) | ||
41 | { | ||
42 | PDEBUG_LOCKS("called.\n"); | ||
43 | return dlist->n; | ||
44 | } | ||
45 | |||
46 | me_device_t *me_dlist_get_device(struct me_dlist * dlist, unsigned int index) | ||
47 | { | ||
48 | |||
49 | struct list_head *pos; | ||
50 | me_device_t *device = NULL; | ||
51 | unsigned int i = 0; | ||
52 | |||
53 | PDEBUG_LOCKS("called.\n"); | ||
54 | |||
55 | if (index >= dlist->n) { | ||
56 | PERROR("Index out of range.\n"); | ||
57 | return NULL; | ||
58 | } | ||
59 | |||
60 | list_for_each(pos, &dlist->head) { | ||
61 | if (i == index) { | ||
62 | device = list_entry(pos, me_device_t, list); | ||
63 | break; | ||
64 | } | ||
65 | |||
66 | ++i; | ||
67 | } | ||
68 | |||
69 | return device; | ||
70 | } | ||
71 | |||
72 | void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t *device) | ||
73 | { | ||
74 | PDEBUG_LOCKS("called.\n"); | ||
75 | |||
76 | list_add_tail(&device->list, &dlist->head); | ||
77 | ++dlist->n; | ||
78 | } | ||
79 | |||
80 | me_device_t *me_dlist_del_device_tail(struct me_dlist *dlist) | ||
81 | { | ||
82 | |||
83 | struct list_head *last; | ||
84 | me_device_t *device; | ||
85 | |||
86 | PDEBUG_LOCKS("called.\n"); | ||
87 | |||
88 | if (list_empty(&dlist->head)) | ||
89 | return NULL; | ||
90 | |||
91 | last = dlist->head.prev; | ||
92 | |||
93 | device = list_entry(last, me_device_t, list); | ||
94 | |||
95 | list_del(last); | ||
96 | |||
97 | --dlist->n; | ||
98 | |||
99 | return device; | ||
100 | } | ||
101 | |||
102 | int me_dlist_init(me_dlist_t *dlist) | ||
103 | { | ||
104 | PDEBUG_LOCKS("called.\n"); | ||
105 | |||
106 | INIT_LIST_HEAD(&dlist->head); | ||
107 | dlist->n = 0; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | void me_dlist_deinit(me_dlist_t *dlist) | ||
112 | { | ||
113 | |||
114 | struct list_head *s; | ||
115 | me_device_t *device; | ||
116 | |||
117 | PDEBUG_LOCKS("called.\n"); | ||
118 | |||
119 | while (!list_empty(&dlist->head)) { | ||
120 | s = dlist->head.next; | ||
121 | list_del(s); | ||
122 | device = list_entry(s, me_device_t, list); | ||
123 | device->me_device_destructor(device); | ||
124 | } | ||
125 | |||
126 | dlist->n = 0; | ||
127 | } | ||
diff --git a/drivers/staging/meilhaus/medlist.h b/drivers/staging/meilhaus/medlist.h deleted file mode 100644 index 091c11e48ed2..000000000000 --- a/drivers/staging/meilhaus/medlist.h +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | /** | ||
2 | * @file me_dlist.h | ||
3 | * | ||
4 | * @brief Provides the device list class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME_DLIST_H_ | ||
10 | #define _ME_DLIST_H_ | ||
11 | |||
12 | #include <linux/list.h> | ||
13 | |||
14 | #include "medevice.h" | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | |||
18 | /** | ||
19 | * @brief The device list container. | ||
20 | */ | ||
21 | typedef struct me_dlist { | ||
22 | struct list_head head; /**< The head of the internal list. */ | ||
23 | unsigned int n; /**< The number of devices in the list. */ | ||
24 | } me_dlist_t; | ||
25 | |||
26 | /** | ||
27 | * @brief Queries the number of devices currently inside the list. | ||
28 | * | ||
29 | * @param dlist The device list to query. | ||
30 | * @param[out] number The number of devices. | ||
31 | * | ||
32 | * @return ME-iDS error code. | ||
33 | */ | ||
34 | int me_dlist_query_number_devices(struct me_dlist *dlist, int *number); | ||
35 | |||
36 | /** | ||
37 | * @brief Returns the number of devices currently inside the list. | ||
38 | * | ||
39 | * @param dlist The device list to query. | ||
40 | * | ||
41 | * @return The number of devices in the list. | ||
42 | */ | ||
43 | unsigned int me_dlist_get_number_devices(struct me_dlist *dlist); | ||
44 | |||
45 | /** | ||
46 | * @brief Get a device by index. | ||
47 | * | ||
48 | * @param dlist The device list to query. | ||
49 | * @param index The index of the device to get in the list. | ||
50 | * | ||
51 | * @return The device at index if available.\n | ||
52 | * NULL if the index is out of range. | ||
53 | */ | ||
54 | me_device_t *me_dlist_get_device(struct me_dlist *dlist, unsigned int index); | ||
55 | |||
56 | /** | ||
57 | * @brief Adds a device to the tail of the list. | ||
58 | * | ||
59 | * @param dlist The device list to add a device to. | ||
60 | * @param device The device to add to the list. | ||
61 | */ | ||
62 | void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t * device); | ||
63 | |||
64 | /** | ||
65 | * @brief Removes a device from the tail of the list. | ||
66 | * | ||
67 | * @param dlist The device list. | ||
68 | * | ||
69 | * @return Pointer to the removed subdeivce.\n | ||
70 | * NULL in cases where the list was empty. | ||
71 | */ | ||
72 | me_device_t *me_dlist_del_device_tail(struct me_dlist *dlist); | ||
73 | |||
74 | /** | ||
75 | * @brief Initializes a device list structure. | ||
76 | * | ||
77 | * @param lock The device list structure to initialize. | ||
78 | * @return 0 on success. | ||
79 | */ | ||
80 | int me_dlist_init(me_dlist_t * dlist); | ||
81 | |||
82 | /** | ||
83 | * @brief Deinitializes a device list structure and destructs every device in it. | ||
84 | * | ||
85 | * @param dlist The device list structure to deinitialize. | ||
86 | * @return 0 on success. | ||
87 | */ | ||
88 | void me_dlist_deinit(me_dlist_t * dlist); | ||
89 | |||
90 | #endif | ||
91 | #endif | ||
diff --git a/drivers/staging/meilhaus/medlock.c b/drivers/staging/meilhaus/medlock.c deleted file mode 100644 index 8ded397214f8..000000000000 --- a/drivers/staging/meilhaus/medlock.c +++ /dev/null | |||
@@ -1,195 +0,0 @@ | |||
1 | /** | ||
2 | * @file medlock.c | ||
3 | * | ||
4 | * @brief Implements the device lock class. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include <linux/spinlock.h> | ||
28 | |||
29 | #include "medefines.h" | ||
30 | #include "meerror.h" | ||
31 | |||
32 | #include "medebug.h" | ||
33 | #include "meslist.h" | ||
34 | #include "mesubdevice.h" | ||
35 | #include "medlock.h" | ||
36 | |||
37 | int me_dlock_enter(struct me_dlock *dlock, struct file *filep) | ||
38 | { | ||
39 | PDEBUG_LOCKS("executed.\n"); | ||
40 | |||
41 | spin_lock(&dlock->spin_lock); | ||
42 | |||
43 | if ((dlock->filep) != NULL && (dlock->filep != filep)) { | ||
44 | PERROR("Device is locked by another process.\n"); | ||
45 | spin_unlock(&dlock->spin_lock); | ||
46 | return ME_ERRNO_LOCKED; | ||
47 | } | ||
48 | |||
49 | dlock->count++; | ||
50 | |||
51 | spin_unlock(&dlock->spin_lock); | ||
52 | |||
53 | return ME_ERRNO_SUCCESS; | ||
54 | } | ||
55 | |||
56 | int me_dlock_exit(struct me_dlock *dlock, struct file *filep) | ||
57 | { | ||
58 | PDEBUG_LOCKS("executed.\n"); | ||
59 | |||
60 | spin_lock(&dlock->spin_lock); | ||
61 | dlock->count--; | ||
62 | spin_unlock(&dlock->spin_lock); | ||
63 | |||
64 | return ME_ERRNO_SUCCESS; | ||
65 | } | ||
66 | |||
67 | int me_dlock_lock(struct me_dlock *dlock, | ||
68 | struct file *filep, int lock, int flags, me_slist_t *slist) | ||
69 | { | ||
70 | int err = ME_ERRNO_SUCCESS; | ||
71 | int i; | ||
72 | me_subdevice_t *subdevice; | ||
73 | |||
74 | PDEBUG_LOCKS("executed.\n"); | ||
75 | |||
76 | spin_lock(&dlock->spin_lock); | ||
77 | |||
78 | switch (lock) { | ||
79 | |||
80 | case ME_LOCK_RELEASE: | ||
81 | if ((dlock->filep == filep) || (dlock->filep == NULL)) { | ||
82 | dlock->filep = NULL; | ||
83 | |||
84 | /* Unlock all possibly locked subdevices. */ | ||
85 | |||
86 | for (i = 0; i < me_slist_get_number_subdevices(slist); | ||
87 | i++) { | ||
88 | subdevice = me_slist_get_subdevice(slist, i); | ||
89 | |||
90 | if (subdevice) | ||
91 | err = | ||
92 | subdevice-> | ||
93 | me_subdevice_lock_subdevice | ||
94 | (subdevice, filep, ME_LOCK_RELEASE, | ||
95 | flags); | ||
96 | else | ||
97 | err = ME_ERRNO_INTERNAL; | ||
98 | } | ||
99 | } | ||
100 | |||
101 | break; | ||
102 | |||
103 | case ME_LOCK_SET: | ||
104 | if (dlock->count) { | ||
105 | PERROR("Device is used by another process.\n"); | ||
106 | err = ME_ERRNO_USED; | ||
107 | } else if ((dlock->filep != NULL) && (dlock->filep != filep)) { | ||
108 | PERROR("Device is locked by another process.\n"); | ||
109 | err = ME_ERRNO_LOCKED; | ||
110 | } else if (dlock->filep == NULL) { | ||
111 | /* Check any subdevice is locked by another process. */ | ||
112 | |||
113 | for (i = 0; i < me_slist_get_number_subdevices(slist); | ||
114 | i++) { | ||
115 | subdevice = me_slist_get_subdevice(slist, i); | ||
116 | |||
117 | if (subdevice) { | ||
118 | if ((err = | ||
119 | subdevice-> | ||
120 | me_subdevice_lock_subdevice | ||
121 | (subdevice, filep, ME_LOCK_CHECK, | ||
122 | flags))) { | ||
123 | PERROR | ||
124 | ("A subdevice is locked by another process.\n"); | ||
125 | break; | ||
126 | } | ||
127 | } else { | ||
128 | err = ME_ERRNO_INTERNAL; | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /* If no subdevices are locked by other processes, | ||
133 | we can take ownership of the device. Otherwise we jump ahead. */ | ||
134 | if (!err) | ||
135 | dlock->filep = filep; | ||
136 | } | ||
137 | |||
138 | break; | ||
139 | |||
140 | case ME_LOCK_CHECK: | ||
141 | if (dlock->count) { | ||
142 | err = ME_ERRNO_USED; | ||
143 | } else if ((dlock->filep != NULL) && (dlock->filep != filep)) { | ||
144 | err = ME_ERRNO_LOCKED; | ||
145 | } else if (dlock->filep == NULL) { | ||
146 | for (i = 0; i < me_slist_get_number_subdevices(slist); | ||
147 | i++) { | ||
148 | subdevice = me_slist_get_subdevice(slist, i); | ||
149 | |||
150 | if (subdevice) { | ||
151 | if ((err = | ||
152 | subdevice-> | ||
153 | me_subdevice_lock_subdevice | ||
154 | (subdevice, filep, ME_LOCK_CHECK, | ||
155 | flags))) { | ||
156 | PERROR | ||
157 | ("A subdevice is locked by another process.\n"); | ||
158 | break; | ||
159 | } | ||
160 | } else { | ||
161 | err = ME_ERRNO_INTERNAL; | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | |||
166 | break; | ||
167 | |||
168 | default: | ||
169 | PERROR("Invalid lock.\n"); | ||
170 | |||
171 | err = ME_ERRNO_INVALID_LOCK; | ||
172 | |||
173 | break; | ||
174 | } | ||
175 | |||
176 | spin_unlock(&dlock->spin_lock); | ||
177 | |||
178 | return err; | ||
179 | } | ||
180 | |||
181 | void me_dlock_deinit(struct me_dlock *dlock) | ||
182 | { | ||
183 | PDEBUG_LOCKS("executed.\n"); | ||
184 | } | ||
185 | |||
186 | int me_dlock_init(me_dlock_t *dlock) | ||
187 | { | ||
188 | PDEBUG_LOCKS("executed.\n"); | ||
189 | |||
190 | dlock->filep = NULL; | ||
191 | dlock->count = 0; | ||
192 | spin_lock_init(&dlock->spin_lock); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
diff --git a/drivers/staging/meilhaus/medlock.h b/drivers/staging/meilhaus/medlock.h deleted file mode 100644 index 4d6ddc8e58a1..000000000000 --- a/drivers/staging/meilhaus/medlock.h +++ /dev/null | |||
@@ -1,76 +0,0 @@ | |||
1 | /** | ||
2 | * @file medlock.h | ||
3 | * | ||
4 | * @brief Provides the device lock class. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _MEDLOCK_H_ | ||
10 | #define _MEDLOCK_H_ | ||
11 | |||
12 | #include <linux/spinlock.h> | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | |||
16 | /** | ||
17 | * @brief The device lock class. | ||
18 | */ | ||
19 | typedef struct me_dlock { | ||
20 | struct file *filep; /**< Pointer to file structure holding the device. */ | ||
21 | int count; /**< Number of tasks which are inside the device. */ | ||
22 | spinlock_t spin_lock; /**< Spin lock protecting the attributes from concurrent access. */ | ||
23 | } me_dlock_t; | ||
24 | |||
25 | /** | ||
26 | * @brief Tries to enter a device. | ||
27 | * | ||
28 | * @param dlock The device lock instance. | ||
29 | * @param filep The file structure identifying the calling process. | ||
30 | * | ||
31 | * @return 0 on success. | ||
32 | */ | ||
33 | int me_dlock_enter(struct me_dlock *dlock, struct file *filep); | ||
34 | |||
35 | /** | ||
36 | * @brief Exits a device. | ||
37 | * | ||
38 | * @param dlock The device lock instance. | ||
39 | * @param filep The file structure identifying the calling process. | ||
40 | * | ||
41 | * @return 0 on success. | ||
42 | */ | ||
43 | int me_dlock_exit(struct me_dlock *dlock, struct file *filep); | ||
44 | |||
45 | /** | ||
46 | * @brief Tries to perform a locking action on a device. | ||
47 | * | ||
48 | * @param dlock The device lock instance. | ||
49 | * @param filep The file structure identifying the calling process. | ||
50 | * @param The action to be done. | ||
51 | * @param flags Flags from user space. | ||
52 | * @param slist The subdevice list of the device. | ||
53 | * | ||
54 | * @return 0 on success. | ||
55 | */ | ||
56 | int me_dlock_lock(struct me_dlock *dlock, | ||
57 | struct file *filep, int lock, int flags, me_slist_t * slist); | ||
58 | |||
59 | /** | ||
60 | * @brief Initializes a lock structure. | ||
61 | * | ||
62 | * @param dlock The lock structure to initialize. | ||
63 | * @return 0 on success. | ||
64 | */ | ||
65 | int me_dlock_init(me_dlock_t * dlock); | ||
66 | |||
67 | /** | ||
68 | * @brief Deinitializes a lock structure. | ||
69 | * | ||
70 | * @param dlock The lock structure to deinitialize. | ||
71 | * @return 0 on success. | ||
72 | */ | ||
73 | void me_dlock_deinit(me_dlock_t * dlock); | ||
74 | |||
75 | #endif | ||
76 | #endif | ||
diff --git a/drivers/staging/meilhaus/medriver.h b/drivers/staging/meilhaus/medriver.h deleted file mode 100644 index 02e2408ce5f3..000000000000 --- a/drivers/staging/meilhaus/medriver.h +++ /dev/null | |||
@@ -1,350 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : medriver.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | * Author: Krzysztof Gantzke <k.gantzke@meilhaus.de> | ||
7 | */ | ||
8 | |||
9 | #ifndef _MEDRIVER_H_ | ||
10 | #define _MEDRIVER_H_ | ||
11 | |||
12 | #include "metypes.h" | ||
13 | #include "meerror.h" | ||
14 | #include "medefines.h" | ||
15 | |||
16 | #ifdef __cplusplus | ||
17 | extern "C" { | ||
18 | #endif | ||
19 | |||
20 | /*=========================================================================== | ||
21 | Functions to access the driver system | ||
22 | =========================================================================*/ | ||
23 | |||
24 | int meOpen(int iFlags); | ||
25 | int meClose(int iFlags); | ||
26 | |||
27 | int meLockDriver(int iLock, int iFlags); | ||
28 | int meLockDevice(int iDevice, int iLock, int iFlags); | ||
29 | int meLockSubdevice(int iDevice, int iSubdevice, int iLock, int iFlags); | ||
30 | |||
31 | /*=========================================================================== | ||
32 | Error handling functions | ||
33 | =========================================================================*/ | ||
34 | |||
35 | int meErrorGetLastMessage(char *pcErrorMsg, int iCount); | ||
36 | int meErrorGetMessage(int iErrorCode, char *pcErrorMsg, int iCount); | ||
37 | int meErrorSetDefaultProc(int iSwitch); | ||
38 | int meErrorSetUserProc(meErrorCB_t pErrorProc); | ||
39 | |||
40 | |||
41 | /*=========================================================================== | ||
42 | Functions to perform I/O on a device | ||
43 | =========================================================================*/ | ||
44 | |||
45 | int meIOIrqSetCallback( | ||
46 | int iDevice, | ||
47 | int iSubdevice, | ||
48 | meIOIrqCB_t pCallback, | ||
49 | void *pCallbackContext, | ||
50 | int iFlags); | ||
51 | int meIOIrqStart( | ||
52 | int iDevice, | ||
53 | int iSubdevice, | ||
54 | int iChannel, | ||
55 | int iIrqSource, | ||
56 | int iIrqEdge, | ||
57 | int iIrqArg, | ||
58 | int iFlags); | ||
59 | int meIOIrqStop( | ||
60 | int iDevice, | ||
61 | int iSubdevice, | ||
62 | int iChannel, | ||
63 | int iFlags); | ||
64 | int meIOIrqWait( | ||
65 | int iDevice, | ||
66 | int iSubdevice, | ||
67 | int iChannel, | ||
68 | int *piIrqCount, | ||
69 | int *piValue, | ||
70 | int iTimeOut, | ||
71 | int iFlags); | ||
72 | |||
73 | int meIOResetDevice(int iDevice, int iFlags); | ||
74 | int meIOResetSubdevice(int iDevice, int iSubdevice, int iFlags); | ||
75 | |||
76 | int meIOStreamFrequencyToTicks( | ||
77 | int iDevice, | ||
78 | int iSubdevice, | ||
79 | int iTimer, | ||
80 | double *pdFrequency, | ||
81 | int *piTicksLow, | ||
82 | int *piTicksHigh, | ||
83 | int iFlags); | ||
84 | |||
85 | int meIOSingleConfig( | ||
86 | int iDevice, | ||
87 | int iSubdevice, | ||
88 | int iChannel, | ||
89 | int iSingleConfig, | ||
90 | int iRef, | ||
91 | int iTrigChan, | ||
92 | int iTrigType, | ||
93 | int iTrigEdge, | ||
94 | int iFlags); | ||
95 | int meIOSingle(meIOSingle_t *pSingleList, int iCount, int iFlags); | ||
96 | |||
97 | int meIOStreamConfig( | ||
98 | int iDevice, | ||
99 | int iSubdevice, | ||
100 | meIOStreamConfig_t *pConfigList, | ||
101 | int iCount, | ||
102 | meIOStreamTrigger_t *pTrigger, | ||
103 | int iFifoIrqThreshold, | ||
104 | int iFlags); | ||
105 | int meIOStreamNewValues( | ||
106 | int iDevice, | ||
107 | int iSubdevice, | ||
108 | int iTimeOut, | ||
109 | int *piCount, | ||
110 | int iFlags); | ||
111 | int meIOStreamRead( | ||
112 | int iDevice, | ||
113 | int iSubdevice, | ||
114 | int iReadMode, | ||
115 | int *piValues, | ||
116 | int *piCount, | ||
117 | int iFlags); | ||
118 | int meIOStreamWrite( | ||
119 | int iDevice, | ||
120 | int iSubdevice, | ||
121 | int iWriteMode, | ||
122 | int *piValues, | ||
123 | int *piCount, | ||
124 | int iFlags); | ||
125 | int meIOStreamStart(meIOStreamStart_t *pStartList, int iCount, int iFlags); | ||
126 | int meIOStreamStop(meIOStreamStop_t *pStopList, int iCount, int iFlags); | ||
127 | int meIOStreamStatus( | ||
128 | int iDevice, | ||
129 | int iSubdevice, | ||
130 | int iWait, | ||
131 | int *piStatus, | ||
132 | int *piCount, | ||
133 | int iFlags); | ||
134 | int meIOStreamSetCallbacks( | ||
135 | int iDevice, | ||
136 | int iSubdevice, | ||
137 | meIOStreamCB_t pStartCB, | ||
138 | void *pStartCBContext, | ||
139 | meIOStreamCB_t pNewValuesCB, | ||
140 | void *pNewValuesCBContext, | ||
141 | meIOStreamCB_t pEndCB, | ||
142 | void *pEndCBContext, | ||
143 | int iFlags); | ||
144 | int meIOStreamTimeToTicks( | ||
145 | int iDevice, | ||
146 | int iSubdevice, | ||
147 | int iTimer, | ||
148 | double *pdTime, | ||
149 | int *piTicksLow, | ||
150 | int *piTicksHigh, | ||
151 | int iFlags); | ||
152 | |||
153 | |||
154 | /*=========================================================================== | ||
155 | Functions to query the driver system | ||
156 | =========================================================================*/ | ||
157 | |||
158 | int meQueryDescriptionDevice(int iDevice, char *pcDescription, int iCount); | ||
159 | |||
160 | int meQueryInfoDevice( | ||
161 | int iDevice, | ||
162 | int *piVendorId, | ||
163 | int *piDeviceId, | ||
164 | int *piSerialNo, | ||
165 | int *piBusType, | ||
166 | int *piBusNo, | ||
167 | int *piDevNo, | ||
168 | int *piFuncNo, | ||
169 | int *piPlugged); | ||
170 | |||
171 | int meQueryNameDevice(int iDevice, char *pcName, int iCount); | ||
172 | int meQueryNameDeviceDriver(int iDevice, char *pcName, int iCount); | ||
173 | |||
174 | int meQueryNumberDevices(int *piNumber); | ||
175 | int meQueryNumberSubdevices(int iDevice, int *piNumber); | ||
176 | int meQueryNumberChannels(int iDevice, int iSubdevice, int *piNumber); | ||
177 | int meQueryNumberRanges( | ||
178 | int iDevice, | ||
179 | int iSubdevice, | ||
180 | int iUnit, | ||
181 | int *piNumber); | ||
182 | |||
183 | int meQueryRangeByMinMax( | ||
184 | int iDevice, | ||
185 | int iSubdevice, | ||
186 | int iUnit, | ||
187 | double *pdMin, | ||
188 | double *pdMax, | ||
189 | int *piMaxData, | ||
190 | int *piRange); | ||
191 | int meQueryRangeInfo( | ||
192 | int iDevice, | ||
193 | int iSubdevice, | ||
194 | int iRange, | ||
195 | int *piUnit, | ||
196 | double *pdMin, | ||
197 | double *pdMax, | ||
198 | int *piMaxData); | ||
199 | |||
200 | int meQuerySubdeviceByType( | ||
201 | int iDevice, | ||
202 | int iStartSubdevice, | ||
203 | int iType, | ||
204 | int iSubtype, | ||
205 | int *piSubdevice); | ||
206 | int meQuerySubdeviceType( | ||
207 | int iDevice, | ||
208 | int iSubdevice, | ||
209 | int *piType, | ||
210 | int *piSubtype); | ||
211 | int meQuerySubdeviceCaps( | ||
212 | int iDevice, | ||
213 | int iSubdevice, | ||
214 | int *piCaps); | ||
215 | int meQuerySubdeviceCapsArgs( | ||
216 | int iDevice, | ||
217 | int iSubdevice, | ||
218 | int iCap, | ||
219 | int *piArgs, | ||
220 | int iCount); | ||
221 | |||
222 | int meQueryVersionLibrary(int *piVersion); | ||
223 | int meQueryVersionMainDriver(int *piVersion); | ||
224 | int meQueryVersionDeviceDriver(int iDevice, int *piVersion); | ||
225 | |||
226 | |||
227 | /*=========================================================================== | ||
228 | Common utility functions | ||
229 | =========================================================================*/ | ||
230 | |||
231 | int meUtilityExtractValues( | ||
232 | int iChannel, | ||
233 | int *piAIBuffer, | ||
234 | int iAIBufferCount, | ||
235 | meIOStreamConfig_t *pConfigList, | ||
236 | int iConfigListCount, | ||
237 | int *piChanBuffer, | ||
238 | int *piChanBufferCount); | ||
239 | int meUtilityDigitalToPhysical( | ||
240 | double dMin, | ||
241 | double dMax, | ||
242 | int iMaxData, | ||
243 | int iData, | ||
244 | int iModuleType, | ||
245 | double dRefValue, | ||
246 | double *pdPhysical); | ||
247 | int meUtilityDigitalToPhysicalV( | ||
248 | double dMin, | ||
249 | double dMax, | ||
250 | int iMaxData, | ||
251 | int *piDataBuffer, | ||
252 | int iCount, | ||
253 | int iModuleType, | ||
254 | double dRefValue, | ||
255 | double *pdPhysicalBuffer); | ||
256 | int meUtilityPhysicalToDigital( | ||
257 | double dMin, | ||
258 | double dMax, | ||
259 | int iMaxData, | ||
260 | double dPhysical, | ||
261 | int *piData); | ||
262 | int meUtilityPWMStart( | ||
263 | int iDevice, | ||
264 | int iSubdevice1, | ||
265 | int iSubdevice2, | ||
266 | int iSubdevice3, | ||
267 | int iRef, | ||
268 | int iPrescaler, | ||
269 | int iDutyCycle, | ||
270 | int iFlag); | ||
271 | int meUtilityPWMStop(int iDevice, | ||
272 | int iSubdevice1); | ||
273 | int meUtilityPWMRestart( | ||
274 | int iDevice, | ||
275 | int iSubdevice1, | ||
276 | int iRef, | ||
277 | int iPrescaler); | ||
278 | |||
279 | |||
280 | /*=========================================================================== | ||
281 | Load configuration from file into driver system | ||
282 | =========================================================================*/ | ||
283 | |||
284 | int meConfigLoad(char *pcConfigFile); | ||
285 | |||
286 | |||
287 | /*=========================================================================== | ||
288 | Functions to query a remote driver system | ||
289 | =========================================================================*/ | ||
290 | |||
291 | int meRQueryDescriptionDevice( | ||
292 | char *location, | ||
293 | int iDevice, | ||
294 | char *pcDescription, | ||
295 | int iCount); | ||
296 | |||
297 | int meRQueryInfoDevice( | ||
298 | char *location, | ||
299 | int iDevice, | ||
300 | int *piVendorId, | ||
301 | int *piDeviceId, | ||
302 | int *piSerialNo, | ||
303 | int *piBusType, | ||
304 | int *piBusNo, | ||
305 | int *piDevNo, | ||
306 | int *piFuncNo, | ||
307 | int *piPlugged); | ||
308 | |||
309 | int meRQueryNameDevice( | ||
310 | char *location, | ||
311 | int iDevice, | ||
312 | char *pcName, | ||
313 | int iCount); | ||
314 | |||
315 | int meRQueryNumberDevices(char *location, int *piNumber); | ||
316 | int meRQueryNumberSubdevices(char *location, int iDevice, int *piNumber); | ||
317 | int meRQueryNumberChannels( | ||
318 | char *location, | ||
319 | int iDevice, | ||
320 | int iSubdevice, | ||
321 | int *piNumber); | ||
322 | int meRQueryNumberRanges( | ||
323 | char *location, | ||
324 | int iDevice, | ||
325 | int iSubdevice, | ||
326 | int iUnit, | ||
327 | int *piNumber); | ||
328 | |||
329 | int meRQueryRangeInfo( | ||
330 | char *location, | ||
331 | int iDevice, | ||
332 | int iSubdevice, | ||
333 | int iRange, | ||
334 | int *piUnit, | ||
335 | double *pdMin, | ||
336 | double *pdMax, | ||
337 | int *piMaxData); | ||
338 | |||
339 | int meRQuerySubdeviceType( | ||
340 | char *location, | ||
341 | int iDevice, | ||
342 | int iSubdevice, | ||
343 | int *piType, | ||
344 | int *piSubtype); | ||
345 | |||
346 | #ifdef __cplusplus | ||
347 | } | ||
348 | #endif | ||
349 | |||
350 | #endif | ||
diff --git a/drivers/staging/meilhaus/medummy.c b/drivers/staging/meilhaus/medummy.c deleted file mode 100644 index 2423745f9575..000000000000 --- a/drivers/staging/meilhaus/medummy.c +++ /dev/null | |||
@@ -1,1264 +0,0 @@ | |||
1 | /* Device driver for Meilhaus ME-DUMMY devices. | ||
2 | * =========================================== | ||
3 | * | ||
4 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
5 | * | ||
6 | * This file is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * User application could also include the kernel header files. But the | ||
23 | * real kernel functions are protected by #ifdef __KERNEL__. | ||
24 | */ | ||
25 | #ifndef __KERNEL__ | ||
26 | # define __KERNEL__ | ||
27 | #endif | ||
28 | |||
29 | /* | ||
30 | * This must be defined before module.h is included. Not needed, when | ||
31 | * it is a built in driver. | ||
32 | */ | ||
33 | #ifndef MODULE | ||
34 | # define MODULE | ||
35 | #endif | ||
36 | |||
37 | #include <linux/module.h> | ||
38 | #include <linux/slab.h> | ||
39 | |||
40 | #include "meerror.h" | ||
41 | #include "meinternal.h" | ||
42 | |||
43 | #include "meids.h" | ||
44 | #include "mecommon.h" | ||
45 | #include "medevice.h" | ||
46 | #include "medebug.h" | ||
47 | |||
48 | #include "medummy.h" | ||
49 | |||
50 | static int medummy_io_irq_start(me_device_t *device, | ||
51 | struct file *filep, | ||
52 | int subdevice, | ||
53 | int channel, | ||
54 | int irq_source, | ||
55 | int irq_edge, int irq_arg, int flags) | ||
56 | { | ||
57 | PDEBUG("executed.\n"); | ||
58 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
59 | } | ||
60 | |||
61 | static int medummy_io_irq_wait(me_device_t *device, | ||
62 | struct file *filep, | ||
63 | int subdevice, | ||
64 | int channel, | ||
65 | int *irq_count, | ||
66 | int *value, int timeout, int flags) | ||
67 | { | ||
68 | PDEBUG("executed.\n"); | ||
69 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
70 | } | ||
71 | |||
72 | static int medummy_io_irq_stop(me_device_t *device, | ||
73 | struct file *filep, | ||
74 | int subdevice, int channel, int flags) | ||
75 | { | ||
76 | PDEBUG("executed.\n"); | ||
77 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
78 | } | ||
79 | |||
80 | static int medummy_io_reset_device(me_device_t *device, | ||
81 | struct file *filep, int flags) | ||
82 | { | ||
83 | PDEBUG("executed.\n"); | ||
84 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
85 | } | ||
86 | |||
87 | static int medummy_io_reset_subdevice(me_device_t *device, | ||
88 | struct file *filep, | ||
89 | int subdevice, int flags) | ||
90 | { | ||
91 | PDEBUG("executed.\n"); | ||
92 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
93 | } | ||
94 | |||
95 | static int medummy_io_single_config(me_device_t *device, | ||
96 | struct file *filep, | ||
97 | int subdevice, | ||
98 | int channel, | ||
99 | int single_config, | ||
100 | int ref, | ||
101 | int trig_chan, | ||
102 | int trig_type, int trig_edge, int flags) | ||
103 | { | ||
104 | PDEBUG("executed.\n"); | ||
105 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
106 | } | ||
107 | |||
108 | static int medummy_io_single_read(me_device_t *device, | ||
109 | struct file *filep, | ||
110 | int subdevice, | ||
111 | int channel, | ||
112 | int *value, int time_out, int flags) | ||
113 | { | ||
114 | PDEBUG("executed.\n"); | ||
115 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
116 | } | ||
117 | |||
118 | static int medummy_io_single_write(me_device_t *device, | ||
119 | struct file *filep, | ||
120 | int subdevice, | ||
121 | int channel, | ||
122 | int value, int time_out, int flags) | ||
123 | { | ||
124 | PDEBUG("executed.\n"); | ||
125 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
126 | } | ||
127 | |||
128 | static int medummy_io_stream_config(me_device_t *device, | ||
129 | struct file *filep, | ||
130 | int subdevice, | ||
131 | meIOStreamConfig_t *config_list, | ||
132 | int count, | ||
133 | meIOStreamTrigger_t *trigger, | ||
134 | int fifo_irq_threshold, int flags) | ||
135 | { | ||
136 | PDEBUG("executed.\n"); | ||
137 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
138 | } | ||
139 | |||
140 | static int medummy_io_stream_new_values(me_device_t *device, | ||
141 | struct file *filep, | ||
142 | int subdevice, | ||
143 | int timeout, int *count, int flags) | ||
144 | { | ||
145 | PDEBUG("executed.\n"); | ||
146 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
147 | } | ||
148 | |||
149 | static int medummy_io_stream_read(me_device_t *device, | ||
150 | struct file *filep, | ||
151 | int subdevice, | ||
152 | int read_mode, | ||
153 | int *values, int *count, int flags) | ||
154 | { | ||
155 | PDEBUG("executed.\n"); | ||
156 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
157 | } | ||
158 | |||
159 | static int medummy_io_stream_start(me_device_t *device, | ||
160 | struct file *filep, | ||
161 | int subdevice, | ||
162 | int start_mode, int time_out, int flags) | ||
163 | { | ||
164 | PDEBUG("executed.\n"); | ||
165 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
166 | } | ||
167 | |||
168 | static int medummy_io_stream_status(me_device_t *device, | ||
169 | struct file *filep, | ||
170 | int subdevice, | ||
171 | int wait, | ||
172 | int *status, int *values, int flags) | ||
173 | { | ||
174 | PDEBUG("executed.\n"); | ||
175 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
176 | } | ||
177 | |||
178 | static int medummy_io_stream_stop(me_device_t *device, | ||
179 | struct file *filep, | ||
180 | int subdevice, int stop_mode, int flags) | ||
181 | { | ||
182 | PDEBUG("executed.\n"); | ||
183 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
184 | } | ||
185 | |||
186 | static int medummy_io_stream_write(me_device_t *device, | ||
187 | struct file *filep, | ||
188 | int subdevice, | ||
189 | int write_mode, | ||
190 | int *values, int *count, int flags) | ||
191 | { | ||
192 | PDEBUG("executed.\n"); | ||
193 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
194 | } | ||
195 | |||
196 | static int medummy_lock_device(me_device_t *device, | ||
197 | struct file *filep, int lock, int flags) | ||
198 | { | ||
199 | PDEBUG("executed.\n"); | ||
200 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
201 | } | ||
202 | |||
203 | static int medummy_lock_subdevice(me_device_t *device, | ||
204 | struct file *filep, | ||
205 | int subdevice, int lock, int flags) | ||
206 | { | ||
207 | PDEBUG("executed.\n"); | ||
208 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
209 | } | ||
210 | |||
211 | static int medummy_query_description_device(me_device_t *device, | ||
212 | char **description) | ||
213 | { | ||
214 | medummy_device_t *instance = (medummy_device_t *) device; | ||
215 | |||
216 | PDEBUG("executed.\n"); | ||
217 | |||
218 | // if (instance->magic != MEDUMMY_MAGIC_NUMBER) | ||
219 | // { | ||
220 | // PERROR("Wrong magic number.\n"); | ||
221 | // return ME_ERRNO_INTERNAL; | ||
222 | // } | ||
223 | |||
224 | switch (instance->device_id) { | ||
225 | |||
226 | case PCI_DEVICE_ID_MEILHAUS_ME1000: | ||
227 | |||
228 | case PCI_DEVICE_ID_MEILHAUS_ME1000_A: | ||
229 | |||
230 | case PCI_DEVICE_ID_MEILHAUS_ME1000_B: | ||
231 | *description = ME1000_DESCRIPTION_DEVICE_ME1000; | ||
232 | |||
233 | break; | ||
234 | |||
235 | case PCI_DEVICE_ID_MEILHAUS_ME1400: | ||
236 | *description = ME1400_DESCRIPTION_DEVICE_ME1400; | ||
237 | |||
238 | break; | ||
239 | |||
240 | case PCI_DEVICE_ID_MEILHAUS_ME140A: | ||
241 | *description = ME1400_DESCRIPTION_DEVICE_ME1400A; | ||
242 | |||
243 | break; | ||
244 | |||
245 | case PCI_DEVICE_ID_MEILHAUS_ME140B: | ||
246 | *description = ME1400_DESCRIPTION_DEVICE_ME1400B; | ||
247 | |||
248 | break; | ||
249 | |||
250 | case PCI_DEVICE_ID_MEILHAUS_ME14E0: | ||
251 | *description = ME1400_DESCRIPTION_DEVICE_ME1400E; | ||
252 | |||
253 | break; | ||
254 | |||
255 | case PCI_DEVICE_ID_MEILHAUS_ME14EA: | ||
256 | *description = ME1400_DESCRIPTION_DEVICE_ME1400EA; | ||
257 | |||
258 | break; | ||
259 | |||
260 | case PCI_DEVICE_ID_MEILHAUS_ME14EB: | ||
261 | *description = ME1400_DESCRIPTION_DEVICE_ME1400EB; | ||
262 | |||
263 | break; | ||
264 | |||
265 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
266 | *description = ME1400_DESCRIPTION_DEVICE_ME1400C; | ||
267 | |||
268 | break; | ||
269 | |||
270 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
271 | *description = ME1400_DESCRIPTION_DEVICE_ME1400D; | ||
272 | |||
273 | break; | ||
274 | |||
275 | case PCI_DEVICE_ID_MEILHAUS_ME1600_4U: | ||
276 | *description = ME1600_DESCRIPTION_DEVICE_ME16004U; | ||
277 | |||
278 | break; | ||
279 | |||
280 | case PCI_DEVICE_ID_MEILHAUS_ME1600_8U: | ||
281 | *description = ME1600_DESCRIPTION_DEVICE_ME16008U; | ||
282 | |||
283 | break; | ||
284 | |||
285 | case PCI_DEVICE_ID_MEILHAUS_ME1600_12U: | ||
286 | *description = ME1600_DESCRIPTION_DEVICE_ME160012U; | ||
287 | |||
288 | break; | ||
289 | |||
290 | case PCI_DEVICE_ID_MEILHAUS_ME1600_16U: | ||
291 | *description = ME1600_DESCRIPTION_DEVICE_ME160016U; | ||
292 | |||
293 | break; | ||
294 | |||
295 | case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I: | ||
296 | *description = ME1600_DESCRIPTION_DEVICE_ME160016U8I; | ||
297 | |||
298 | break; | ||
299 | |||
300 | case PCI_DEVICE_ID_MEILHAUS_ME4610: | ||
301 | *description = ME4600_DESCRIPTION_DEVICE_ME4610; | ||
302 | |||
303 | break; | ||
304 | |||
305 | case PCI_DEVICE_ID_MEILHAUS_ME4650: | ||
306 | *description = ME4600_DESCRIPTION_DEVICE_ME4650; | ||
307 | |||
308 | break; | ||
309 | |||
310 | case PCI_DEVICE_ID_MEILHAUS_ME4660: | ||
311 | *description = ME4600_DESCRIPTION_DEVICE_ME4660; | ||
312 | |||
313 | break; | ||
314 | |||
315 | case PCI_DEVICE_ID_MEILHAUS_ME4660I: | ||
316 | *description = ME4600_DESCRIPTION_DEVICE_ME4660I; | ||
317 | |||
318 | break; | ||
319 | |||
320 | case PCI_DEVICE_ID_MEILHAUS_ME4660S: | ||
321 | *description = ME4600_DESCRIPTION_DEVICE_ME4660S; | ||
322 | |||
323 | break; | ||
324 | |||
325 | case PCI_DEVICE_ID_MEILHAUS_ME4660IS: | ||
326 | *description = ME4600_DESCRIPTION_DEVICE_ME4660IS; | ||
327 | |||
328 | break; | ||
329 | |||
330 | case PCI_DEVICE_ID_MEILHAUS_ME4670: | ||
331 | *description = ME4600_DESCRIPTION_DEVICE_ME4670; | ||
332 | |||
333 | break; | ||
334 | |||
335 | case PCI_DEVICE_ID_MEILHAUS_ME4670I: | ||
336 | *description = ME4600_DESCRIPTION_DEVICE_ME4670I; | ||
337 | |||
338 | break; | ||
339 | |||
340 | case PCI_DEVICE_ID_MEILHAUS_ME4670S: | ||
341 | *description = ME4600_DESCRIPTION_DEVICE_ME4670S; | ||
342 | |||
343 | break; | ||
344 | |||
345 | case PCI_DEVICE_ID_MEILHAUS_ME4670IS: | ||
346 | *description = ME4600_DESCRIPTION_DEVICE_ME4670IS; | ||
347 | |||
348 | break; | ||
349 | |||
350 | case PCI_DEVICE_ID_MEILHAUS_ME4680: | ||
351 | *description = ME4600_DESCRIPTION_DEVICE_ME4680; | ||
352 | |||
353 | break; | ||
354 | |||
355 | case PCI_DEVICE_ID_MEILHAUS_ME4680I: | ||
356 | *description = ME4600_DESCRIPTION_DEVICE_ME4680I; | ||
357 | |||
358 | break; | ||
359 | |||
360 | case PCI_DEVICE_ID_MEILHAUS_ME4680S: | ||
361 | *description = ME4600_DESCRIPTION_DEVICE_ME4680S; | ||
362 | |||
363 | break; | ||
364 | |||
365 | case PCI_DEVICE_ID_MEILHAUS_ME4680IS: | ||
366 | *description = ME4600_DESCRIPTION_DEVICE_ME4680IS; | ||
367 | |||
368 | break; | ||
369 | |||
370 | case PCI_DEVICE_ID_MEILHAUS_ME6004: | ||
371 | *description = ME6000_DESCRIPTION_DEVICE_ME60004; | ||
372 | |||
373 | break; | ||
374 | |||
375 | case PCI_DEVICE_ID_MEILHAUS_ME6008: | ||
376 | *description = ME6000_DESCRIPTION_DEVICE_ME60008; | ||
377 | |||
378 | break; | ||
379 | |||
380 | case PCI_DEVICE_ID_MEILHAUS_ME600F: | ||
381 | *description = ME6000_DESCRIPTION_DEVICE_ME600016; | ||
382 | |||
383 | break; | ||
384 | |||
385 | case PCI_DEVICE_ID_MEILHAUS_ME6014: | ||
386 | *description = ME6000_DESCRIPTION_DEVICE_ME6000I4; | ||
387 | |||
388 | break; | ||
389 | |||
390 | case PCI_DEVICE_ID_MEILHAUS_ME6018: | ||
391 | *description = ME6000_DESCRIPTION_DEVICE_ME6000I8; | ||
392 | |||
393 | break; | ||
394 | |||
395 | case PCI_DEVICE_ID_MEILHAUS_ME601F: | ||
396 | *description = ME6000_DESCRIPTION_DEVICE_ME6000I16; | ||
397 | |||
398 | break; | ||
399 | |||
400 | case PCI_DEVICE_ID_MEILHAUS_ME6034: | ||
401 | *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4; | ||
402 | |||
403 | break; | ||
404 | |||
405 | case PCI_DEVICE_ID_MEILHAUS_ME6038: | ||
406 | *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8; | ||
407 | |||
408 | break; | ||
409 | |||
410 | case PCI_DEVICE_ID_MEILHAUS_ME603F: | ||
411 | *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16; | ||
412 | |||
413 | break; | ||
414 | |||
415 | case PCI_DEVICE_ID_MEILHAUS_ME6104: | ||
416 | *description = ME6000_DESCRIPTION_DEVICE_ME61004; | ||
417 | |||
418 | break; | ||
419 | |||
420 | case PCI_DEVICE_ID_MEILHAUS_ME6108: | ||
421 | *description = ME6000_DESCRIPTION_DEVICE_ME61008; | ||
422 | |||
423 | break; | ||
424 | |||
425 | case PCI_DEVICE_ID_MEILHAUS_ME610F: | ||
426 | *description = ME6000_DESCRIPTION_DEVICE_ME610016; | ||
427 | |||
428 | break; | ||
429 | |||
430 | case PCI_DEVICE_ID_MEILHAUS_ME6114: | ||
431 | *description = ME6000_DESCRIPTION_DEVICE_ME6100I4; | ||
432 | |||
433 | break; | ||
434 | |||
435 | case PCI_DEVICE_ID_MEILHAUS_ME6118: | ||
436 | *description = ME6000_DESCRIPTION_DEVICE_ME6100I8; | ||
437 | |||
438 | break; | ||
439 | |||
440 | case PCI_DEVICE_ID_MEILHAUS_ME611F: | ||
441 | *description = ME6000_DESCRIPTION_DEVICE_ME6100I16; | ||
442 | |||
443 | break; | ||
444 | |||
445 | case PCI_DEVICE_ID_MEILHAUS_ME6134: | ||
446 | *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4; | ||
447 | |||
448 | break; | ||
449 | |||
450 | case PCI_DEVICE_ID_MEILHAUS_ME6138: | ||
451 | *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8; | ||
452 | |||
453 | break; | ||
454 | |||
455 | case PCI_DEVICE_ID_MEILHAUS_ME613F: | ||
456 | *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16; | ||
457 | |||
458 | break; | ||
459 | |||
460 | case PCI_DEVICE_ID_MEILHAUS_ME6044: | ||
461 | *description = ME6000_DESCRIPTION_DEVICE_ME60004DIO; | ||
462 | |||
463 | break; | ||
464 | |||
465 | case PCI_DEVICE_ID_MEILHAUS_ME6048: | ||
466 | *description = ME6000_DESCRIPTION_DEVICE_ME60008DIO; | ||
467 | |||
468 | break; | ||
469 | |||
470 | case PCI_DEVICE_ID_MEILHAUS_ME604F: | ||
471 | *description = ME6000_DESCRIPTION_DEVICE_ME600016DIO; | ||
472 | |||
473 | break; | ||
474 | |||
475 | case PCI_DEVICE_ID_MEILHAUS_ME6054: | ||
476 | *description = ME6000_DESCRIPTION_DEVICE_ME6000I4DIO; | ||
477 | |||
478 | break; | ||
479 | |||
480 | case PCI_DEVICE_ID_MEILHAUS_ME6058: | ||
481 | *description = ME6000_DESCRIPTION_DEVICE_ME6000I8DIO; | ||
482 | |||
483 | break; | ||
484 | |||
485 | case PCI_DEVICE_ID_MEILHAUS_ME605F: | ||
486 | *description = ME6000_DESCRIPTION_DEVICE_ME6000I16DIO; | ||
487 | |||
488 | break; | ||
489 | |||
490 | case PCI_DEVICE_ID_MEILHAUS_ME6074: | ||
491 | *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO; | ||
492 | |||
493 | break; | ||
494 | |||
495 | case PCI_DEVICE_ID_MEILHAUS_ME6078: | ||
496 | *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO; | ||
497 | |||
498 | break; | ||
499 | |||
500 | case PCI_DEVICE_ID_MEILHAUS_ME607F: | ||
501 | *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO; | ||
502 | |||
503 | break; | ||
504 | |||
505 | case PCI_DEVICE_ID_MEILHAUS_ME6144: | ||
506 | *description = ME6000_DESCRIPTION_DEVICE_ME61004DIO; | ||
507 | |||
508 | break; | ||
509 | |||
510 | case PCI_DEVICE_ID_MEILHAUS_ME6148: | ||
511 | *description = ME6000_DESCRIPTION_DEVICE_ME61008DIO; | ||
512 | |||
513 | break; | ||
514 | |||
515 | case PCI_DEVICE_ID_MEILHAUS_ME614F: | ||
516 | *description = ME6000_DESCRIPTION_DEVICE_ME610016DIO; | ||
517 | |||
518 | break; | ||
519 | |||
520 | case PCI_DEVICE_ID_MEILHAUS_ME6154: | ||
521 | *description = ME6000_DESCRIPTION_DEVICE_ME6100I4DIO; | ||
522 | |||
523 | break; | ||
524 | |||
525 | case PCI_DEVICE_ID_MEILHAUS_ME6158: | ||
526 | *description = ME6000_DESCRIPTION_DEVICE_ME6100I8DIO; | ||
527 | |||
528 | break; | ||
529 | |||
530 | case PCI_DEVICE_ID_MEILHAUS_ME615F: | ||
531 | *description = ME6000_DESCRIPTION_DEVICE_ME6100I16DIO; | ||
532 | |||
533 | break; | ||
534 | |||
535 | case PCI_DEVICE_ID_MEILHAUS_ME6174: | ||
536 | *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO; | ||
537 | |||
538 | break; | ||
539 | |||
540 | case PCI_DEVICE_ID_MEILHAUS_ME6178: | ||
541 | *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO; | ||
542 | |||
543 | break; | ||
544 | |||
545 | case PCI_DEVICE_ID_MEILHAUS_ME617F: | ||
546 | *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO; | ||
547 | |||
548 | break; | ||
549 | |||
550 | case PCI_DEVICE_ID_MEILHAUS_ME6259: | ||
551 | *description = ME6000_DESCRIPTION_DEVICE_ME6200I9DIO; | ||
552 | |||
553 | break; | ||
554 | |||
555 | case PCI_DEVICE_ID_MEILHAUS_ME6359: | ||
556 | *description = ME6000_DESCRIPTION_DEVICE_ME6300I9DIO; | ||
557 | |||
558 | break; | ||
559 | |||
560 | case PCI_DEVICE_ID_MEILHAUS_ME0630: | ||
561 | *description = ME0600_DESCRIPTION_DEVICE_ME0630; | ||
562 | |||
563 | break; | ||
564 | |||
565 | case PCI_DEVICE_ID_MEILHAUS_ME8100_A: | ||
566 | *description = ME8100_DESCRIPTION_DEVICE_ME8100A; | ||
567 | |||
568 | break; | ||
569 | |||
570 | case PCI_DEVICE_ID_MEILHAUS_ME8100_B: | ||
571 | *description = ME8100_DESCRIPTION_DEVICE_ME8100B; | ||
572 | |||
573 | break; | ||
574 | |||
575 | case PCI_DEVICE_ID_MEILHAUS_ME0940: | ||
576 | *description = ME0900_DESCRIPTION_DEVICE_ME0940; | ||
577 | |||
578 | break; | ||
579 | |||
580 | case PCI_DEVICE_ID_MEILHAUS_ME0950: | ||
581 | *description = ME0900_DESCRIPTION_DEVICE_ME0950; | ||
582 | |||
583 | break; | ||
584 | |||
585 | case PCI_DEVICE_ID_MEILHAUS_ME0960: | ||
586 | *description = ME0900_DESCRIPTION_DEVICE_ME0960; | ||
587 | |||
588 | break; | ||
589 | /* | ||
590 | case USB_DEVICE_ID_MEPHISTO_S1: | ||
591 | *description = MEPHISTO_S1_DESCRIPTION_DEVICE; | ||
592 | |||
593 | break; | ||
594 | */ | ||
595 | default: | ||
596 | *description = EMPTY_DESCRIPTION_DEVICE; | ||
597 | PERROR("Invalid device id in device info.\n"); | ||
598 | |||
599 | return ME_ERRNO_INTERNAL; | ||
600 | } | ||
601 | |||
602 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
603 | } | ||
604 | |||
605 | static int medummy_query_info_device(me_device_t *device, | ||
606 | int *vendor_id, | ||
607 | int *device_id, | ||
608 | int *serial_no, | ||
609 | int *bus_type, | ||
610 | int *bus_no, | ||
611 | int *dev_no, int *func_no, int *plugged) | ||
612 | { | ||
613 | medummy_device_t *instance = (medummy_device_t *) device; | ||
614 | |||
615 | PDEBUG("executed.\n"); | ||
616 | |||
617 | // if (instance->magic != MEDUMMY_MAGIC_NUMBER) | ||
618 | // { | ||
619 | // PERROR("Wrong magic number.\n"); | ||
620 | // return ME_ERRNO_INTERNAL; | ||
621 | // } | ||
622 | |||
623 | *vendor_id = instance->vendor_id; | ||
624 | *device_id = instance->device_id; | ||
625 | *serial_no = instance->serial_no; | ||
626 | *bus_type = instance->bus_type; | ||
627 | *bus_no = instance->bus_no; | ||
628 | *dev_no = instance->dev_no; | ||
629 | *func_no = instance->func_no; | ||
630 | *plugged = ME_PLUGGED_OUT; | ||
631 | |||
632 | return ME_ERRNO_SUCCESS; | ||
633 | } | ||
634 | |||
635 | static int medummy_query_name_device_driver(me_device_t *device, char **name) | ||
636 | { | ||
637 | PDEBUG("executed.\n"); | ||
638 | *name = MEDUMMY_NAME_DRIVER; | ||
639 | return ME_ERRNO_SUCCESS; | ||
640 | } | ||
641 | |||
642 | static int medummy_query_name_device(me_device_t *device, char **name) | ||
643 | { | ||
644 | medummy_device_t *instance = (medummy_device_t *) device; | ||
645 | |||
646 | PDEBUG("executed.\n"); | ||
647 | |||
648 | // // // if (instance->magic != MEDUMMY_MAGIC_NUMBER) | ||
649 | // // // { | ||
650 | // // // PERROR("Wrong magic number.\n"); | ||
651 | // // // return ME_ERRNO_INTERNAL; | ||
652 | // // // } | ||
653 | |||
654 | switch (instance->device_id) { | ||
655 | |||
656 | case PCI_DEVICE_ID_MEILHAUS_ME1000: | ||
657 | |||
658 | case PCI_DEVICE_ID_MEILHAUS_ME1000_A: | ||
659 | |||
660 | case PCI_DEVICE_ID_MEILHAUS_ME1000_B: | ||
661 | *name = ME1000_NAME_DEVICE_ME1000; | ||
662 | |||
663 | break; | ||
664 | |||
665 | case PCI_DEVICE_ID_MEILHAUS_ME1400: | ||
666 | *name = ME1400_NAME_DEVICE_ME1400; | ||
667 | |||
668 | break; | ||
669 | |||
670 | case PCI_DEVICE_ID_MEILHAUS_ME140A: | ||
671 | *name = ME1400_NAME_DEVICE_ME1400A; | ||
672 | |||
673 | break; | ||
674 | |||
675 | case PCI_DEVICE_ID_MEILHAUS_ME140B: | ||
676 | *name = ME1400_NAME_DEVICE_ME1400B; | ||
677 | |||
678 | break; | ||
679 | |||
680 | case PCI_DEVICE_ID_MEILHAUS_ME14E0: | ||
681 | *name = ME1400_NAME_DEVICE_ME1400E; | ||
682 | |||
683 | break; | ||
684 | |||
685 | case PCI_DEVICE_ID_MEILHAUS_ME14EA: | ||
686 | *name = ME1400_NAME_DEVICE_ME1400EA; | ||
687 | |||
688 | break; | ||
689 | |||
690 | case PCI_DEVICE_ID_MEILHAUS_ME14EB: | ||
691 | *name = ME1400_NAME_DEVICE_ME1400EB; | ||
692 | |||
693 | break; | ||
694 | |||
695 | case PCI_DEVICE_ID_MEILHAUS_ME140C: | ||
696 | *name = ME1400_NAME_DEVICE_ME1400C; | ||
697 | |||
698 | break; | ||
699 | |||
700 | case PCI_DEVICE_ID_MEILHAUS_ME140D: | ||
701 | *name = ME1400_NAME_DEVICE_ME1400D; | ||
702 | |||
703 | break; | ||
704 | |||
705 | case PCI_DEVICE_ID_MEILHAUS_ME1600_4U: | ||
706 | *name = ME1600_NAME_DEVICE_ME16004U; | ||
707 | |||
708 | break; | ||
709 | |||
710 | case PCI_DEVICE_ID_MEILHAUS_ME1600_8U: | ||
711 | *name = ME1600_NAME_DEVICE_ME16008U; | ||
712 | |||
713 | break; | ||
714 | |||
715 | case PCI_DEVICE_ID_MEILHAUS_ME1600_12U: | ||
716 | *name = ME1600_NAME_DEVICE_ME160012U; | ||
717 | |||
718 | break; | ||
719 | |||
720 | case PCI_DEVICE_ID_MEILHAUS_ME1600_16U: | ||
721 | *name = ME1600_NAME_DEVICE_ME160016U; | ||
722 | |||
723 | break; | ||
724 | |||
725 | case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I: | ||
726 | *name = ME1600_NAME_DEVICE_ME160016U8I; | ||
727 | |||
728 | break; | ||
729 | |||
730 | case PCI_DEVICE_ID_MEILHAUS_ME4610: | ||
731 | *name = ME4600_NAME_DEVICE_ME4610; | ||
732 | |||
733 | break; | ||
734 | |||
735 | case PCI_DEVICE_ID_MEILHAUS_ME4650: | ||
736 | *name = ME4600_NAME_DEVICE_ME4650; | ||
737 | |||
738 | break; | ||
739 | |||
740 | case PCI_DEVICE_ID_MEILHAUS_ME4660: | ||
741 | *name = ME4600_NAME_DEVICE_ME4660; | ||
742 | |||
743 | break; | ||
744 | |||
745 | case PCI_DEVICE_ID_MEILHAUS_ME4660I: | ||
746 | *name = ME4600_NAME_DEVICE_ME4660I; | ||
747 | |||
748 | break; | ||
749 | |||
750 | case PCI_DEVICE_ID_MEILHAUS_ME4670: | ||
751 | *name = ME4600_NAME_DEVICE_ME4670; | ||
752 | |||
753 | break; | ||
754 | |||
755 | case PCI_DEVICE_ID_MEILHAUS_ME4670I: | ||
756 | *name = ME4600_NAME_DEVICE_ME4670I; | ||
757 | |||
758 | break; | ||
759 | |||
760 | case PCI_DEVICE_ID_MEILHAUS_ME4670S: | ||
761 | *name = ME4600_NAME_DEVICE_ME4670S; | ||
762 | |||
763 | break; | ||
764 | |||
765 | case PCI_DEVICE_ID_MEILHAUS_ME4670IS: | ||
766 | *name = ME4600_NAME_DEVICE_ME4670IS; | ||
767 | |||
768 | break; | ||
769 | |||
770 | case PCI_DEVICE_ID_MEILHAUS_ME4680: | ||
771 | *name = ME4600_NAME_DEVICE_ME4680; | ||
772 | |||
773 | break; | ||
774 | |||
775 | case PCI_DEVICE_ID_MEILHAUS_ME4680I: | ||
776 | *name = ME4600_NAME_DEVICE_ME4680I; | ||
777 | |||
778 | break; | ||
779 | |||
780 | case PCI_DEVICE_ID_MEILHAUS_ME4680S: | ||
781 | *name = ME4600_NAME_DEVICE_ME4680S; | ||
782 | |||
783 | break; | ||
784 | |||
785 | case PCI_DEVICE_ID_MEILHAUS_ME4680IS: | ||
786 | *name = ME4600_NAME_DEVICE_ME4680IS; | ||
787 | |||
788 | break; | ||
789 | |||
790 | case PCI_DEVICE_ID_MEILHAUS_ME6004: | ||
791 | *name = ME6000_NAME_DEVICE_ME60004; | ||
792 | |||
793 | break; | ||
794 | |||
795 | case PCI_DEVICE_ID_MEILHAUS_ME6008: | ||
796 | *name = ME6000_NAME_DEVICE_ME60008; | ||
797 | |||
798 | break; | ||
799 | |||
800 | case PCI_DEVICE_ID_MEILHAUS_ME600F: | ||
801 | *name = ME6000_NAME_DEVICE_ME600016; | ||
802 | |||
803 | break; | ||
804 | |||
805 | case PCI_DEVICE_ID_MEILHAUS_ME6014: | ||
806 | *name = ME6000_NAME_DEVICE_ME6000I4; | ||
807 | |||
808 | break; | ||
809 | |||
810 | case PCI_DEVICE_ID_MEILHAUS_ME6018: | ||
811 | *name = ME6000_NAME_DEVICE_ME6000I8; | ||
812 | |||
813 | break; | ||
814 | |||
815 | case PCI_DEVICE_ID_MEILHAUS_ME601F: | ||
816 | *name = ME6000_NAME_DEVICE_ME6000I16; | ||
817 | |||
818 | break; | ||
819 | |||
820 | case PCI_DEVICE_ID_MEILHAUS_ME6034: | ||
821 | *name = ME6000_NAME_DEVICE_ME6000ISLE4; | ||
822 | |||
823 | break; | ||
824 | |||
825 | case PCI_DEVICE_ID_MEILHAUS_ME6038: | ||
826 | *name = ME6000_NAME_DEVICE_ME6000ISLE8; | ||
827 | |||
828 | break; | ||
829 | |||
830 | case PCI_DEVICE_ID_MEILHAUS_ME603F: | ||
831 | *name = ME6000_NAME_DEVICE_ME6000ISLE16; | ||
832 | |||
833 | break; | ||
834 | |||
835 | case PCI_DEVICE_ID_MEILHAUS_ME6104: | ||
836 | *name = ME6000_NAME_DEVICE_ME61004; | ||
837 | |||
838 | break; | ||
839 | |||
840 | case PCI_DEVICE_ID_MEILHAUS_ME6108: | ||
841 | *name = ME6000_NAME_DEVICE_ME61008; | ||
842 | |||
843 | break; | ||
844 | |||
845 | case PCI_DEVICE_ID_MEILHAUS_ME610F: | ||
846 | *name = ME6000_NAME_DEVICE_ME610016; | ||
847 | |||
848 | break; | ||
849 | |||
850 | case PCI_DEVICE_ID_MEILHAUS_ME6114: | ||
851 | *name = ME6000_NAME_DEVICE_ME6100I4; | ||
852 | |||
853 | break; | ||
854 | |||
855 | case PCI_DEVICE_ID_MEILHAUS_ME6118: | ||
856 | *name = ME6000_NAME_DEVICE_ME6100I8; | ||
857 | |||
858 | break; | ||
859 | |||
860 | case PCI_DEVICE_ID_MEILHAUS_ME611F: | ||
861 | *name = ME6000_NAME_DEVICE_ME6100I16; | ||
862 | |||
863 | break; | ||
864 | |||
865 | case PCI_DEVICE_ID_MEILHAUS_ME6134: | ||
866 | *name = ME6000_NAME_DEVICE_ME6100ISLE4; | ||
867 | |||
868 | break; | ||
869 | |||
870 | case PCI_DEVICE_ID_MEILHAUS_ME6138: | ||
871 | *name = ME6000_NAME_DEVICE_ME6100ISLE8; | ||
872 | |||
873 | break; | ||
874 | |||
875 | case PCI_DEVICE_ID_MEILHAUS_ME613F: | ||
876 | *name = ME6000_NAME_DEVICE_ME6100ISLE16; | ||
877 | |||
878 | break; | ||
879 | |||
880 | case PCI_DEVICE_ID_MEILHAUS_ME6044: | ||
881 | *name = ME6000_NAME_DEVICE_ME60004DIO; | ||
882 | |||
883 | break; | ||
884 | |||
885 | case PCI_DEVICE_ID_MEILHAUS_ME6048: | ||
886 | *name = ME6000_NAME_DEVICE_ME60008DIO; | ||
887 | |||
888 | break; | ||
889 | |||
890 | case PCI_DEVICE_ID_MEILHAUS_ME604F: | ||
891 | *name = ME6000_NAME_DEVICE_ME600016DIO; | ||
892 | |||
893 | break; | ||
894 | |||
895 | case PCI_DEVICE_ID_MEILHAUS_ME6054: | ||
896 | *name = ME6000_NAME_DEVICE_ME6000I4DIO; | ||
897 | |||
898 | break; | ||
899 | |||
900 | case PCI_DEVICE_ID_MEILHAUS_ME6058: | ||
901 | *name = ME6000_NAME_DEVICE_ME6000I8DIO; | ||
902 | |||
903 | break; | ||
904 | |||
905 | case PCI_DEVICE_ID_MEILHAUS_ME605F: | ||
906 | *name = ME6000_NAME_DEVICE_ME6000I16DIO; | ||
907 | |||
908 | break; | ||
909 | |||
910 | case PCI_DEVICE_ID_MEILHAUS_ME6074: | ||
911 | *name = ME6000_NAME_DEVICE_ME6000ISLE4DIO; | ||
912 | |||
913 | break; | ||
914 | |||
915 | case PCI_DEVICE_ID_MEILHAUS_ME6078: | ||
916 | *name = ME6000_NAME_DEVICE_ME6000ISLE8DIO; | ||
917 | |||
918 | break; | ||
919 | |||
920 | case PCI_DEVICE_ID_MEILHAUS_ME607F: | ||
921 | *name = ME6000_NAME_DEVICE_ME6000ISLE16DIO; | ||
922 | |||
923 | break; | ||
924 | |||
925 | case PCI_DEVICE_ID_MEILHAUS_ME6144: | ||
926 | *name = ME6000_NAME_DEVICE_ME61004DIO; | ||
927 | |||
928 | break; | ||
929 | |||
930 | case PCI_DEVICE_ID_MEILHAUS_ME6148: | ||
931 | *name = ME6000_NAME_DEVICE_ME61008DIO; | ||
932 | |||
933 | break; | ||
934 | |||
935 | case PCI_DEVICE_ID_MEILHAUS_ME614F: | ||
936 | *name = ME6000_NAME_DEVICE_ME610016DIO; | ||
937 | |||
938 | break; | ||
939 | |||
940 | case PCI_DEVICE_ID_MEILHAUS_ME6154: | ||
941 | *name = ME6000_NAME_DEVICE_ME6100I4DIO; | ||
942 | |||
943 | break; | ||
944 | |||
945 | case PCI_DEVICE_ID_MEILHAUS_ME6158: | ||
946 | *name = ME6000_NAME_DEVICE_ME6100I8DIO; | ||
947 | |||
948 | break; | ||
949 | |||
950 | case PCI_DEVICE_ID_MEILHAUS_ME615F: | ||
951 | *name = ME6000_NAME_DEVICE_ME6100I16DIO; | ||
952 | |||
953 | break; | ||
954 | |||
955 | case PCI_DEVICE_ID_MEILHAUS_ME6174: | ||
956 | *name = ME6000_NAME_DEVICE_ME6100ISLE4DIO; | ||
957 | |||
958 | break; | ||
959 | |||
960 | case PCI_DEVICE_ID_MEILHAUS_ME6178: | ||
961 | *name = ME6000_NAME_DEVICE_ME6100ISLE8DIO; | ||
962 | |||
963 | break; | ||
964 | |||
965 | case PCI_DEVICE_ID_MEILHAUS_ME617F: | ||
966 | *name = ME6000_NAME_DEVICE_ME6100ISLE16DIO; | ||
967 | |||
968 | break; | ||
969 | |||
970 | case PCI_DEVICE_ID_MEILHAUS_ME0630: | ||
971 | *name = ME0600_NAME_DEVICE_ME0630; | ||
972 | |||
973 | break; | ||
974 | |||
975 | case PCI_DEVICE_ID_MEILHAUS_ME8100_A: | ||
976 | *name = ME8100_NAME_DEVICE_ME8100A; | ||
977 | |||
978 | break; | ||
979 | |||
980 | case PCI_DEVICE_ID_MEILHAUS_ME8100_B: | ||
981 | *name = ME8100_NAME_DEVICE_ME8100B; | ||
982 | |||
983 | break; | ||
984 | |||
985 | case PCI_DEVICE_ID_MEILHAUS_ME0940: | ||
986 | *name = ME0900_NAME_DEVICE_ME0940; | ||
987 | |||
988 | break; | ||
989 | |||
990 | case PCI_DEVICE_ID_MEILHAUS_ME0950: | ||
991 | *name = ME0900_NAME_DEVICE_ME0950; | ||
992 | |||
993 | break; | ||
994 | |||
995 | case PCI_DEVICE_ID_MEILHAUS_ME0960: | ||
996 | *name = ME0900_NAME_DEVICE_ME0960; | ||
997 | |||
998 | break; | ||
999 | /* | ||
1000 | case USB_DEVICE_ID_MEPHISTO_S1: | ||
1001 | *name = MEPHISTO_S1_NAME_DEVICE; | ||
1002 | |||
1003 | break; | ||
1004 | */ | ||
1005 | default: | ||
1006 | *name = EMPTY_NAME_DEVICE; | ||
1007 | PERROR("Invalid PCI device id.\n"); | ||
1008 | |||
1009 | return ME_ERRNO_INTERNAL; | ||
1010 | } | ||
1011 | |||
1012 | return ME_ERRNO_SUCCESS; | ||
1013 | } | ||
1014 | |||
1015 | static int medummy_query_number_subdevices(me_device_t *device, int *number) | ||
1016 | { | ||
1017 | PDEBUG("executed.\n"); | ||
1018 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1019 | } | ||
1020 | |||
1021 | static int medummy_query_number_channels(me_device_t *device, | ||
1022 | int subdevice, int *number) | ||
1023 | { | ||
1024 | PDEBUG("executed.\n"); | ||
1025 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1026 | } | ||
1027 | |||
1028 | static int medummy_query_number_ranges(me_device_t *device, | ||
1029 | int subdevice, int unit, int *count) | ||
1030 | { | ||
1031 | PDEBUG("executed.\n"); | ||
1032 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1033 | } | ||
1034 | |||
1035 | static int medummy_query_subdevice_type(me_device_t *device, | ||
1036 | int subdevice, int *type, int *subtype) | ||
1037 | { | ||
1038 | PDEBUG("executed.\n"); | ||
1039 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1040 | } | ||
1041 | |||
1042 | static int medummy_query_subdevice_caps(me_device_t *device, | ||
1043 | int subdevice, int *caps) | ||
1044 | { | ||
1045 | PDEBUG("executed.\n"); | ||
1046 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1047 | } | ||
1048 | |||
1049 | static int medummy_query_subdevice_caps_args(me_device_t *device, | ||
1050 | int subdevice, | ||
1051 | int cap, int *args, int count) | ||
1052 | { | ||
1053 | PDEBUG("executed.\n"); | ||
1054 | return ME_ERRNO_NOT_SUPPORTED; | ||
1055 | } | ||
1056 | |||
1057 | static int medummy_query_subdevice_by_type(me_device_t *device, | ||
1058 | int start_subdevice, | ||
1059 | int type, | ||
1060 | int subtype, int *subdevice) | ||
1061 | { | ||
1062 | PDEBUG("executed.\n"); | ||
1063 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1064 | } | ||
1065 | |||
1066 | static int medummy_query_range_by_min_max(me_device_t *device, | ||
1067 | int subdevice, | ||
1068 | int unit, | ||
1069 | int *min, | ||
1070 | int *max, int *maxdata, int *range) | ||
1071 | { | ||
1072 | PDEBUG("executed.\n"); | ||
1073 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1074 | } | ||
1075 | |||
1076 | static int medummy_query_range_info(me_device_t *device, | ||
1077 | int subdevice, | ||
1078 | int range, | ||
1079 | int *unit, int *min, int *max, int *maxdata) | ||
1080 | { | ||
1081 | PDEBUG("executed.\n"); | ||
1082 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1083 | } | ||
1084 | |||
1085 | int medummy_query_timer(me_device_t *device, | ||
1086 | int subdevice, | ||
1087 | int timer, | ||
1088 | int *base_frequency, | ||
1089 | uint64_t *min_ticks, uint64_t *max_ticks) | ||
1090 | { | ||
1091 | PDEBUG("executed.\n"); | ||
1092 | return ME_ERRNO_DEVICE_UNPLUGGED; | ||
1093 | } | ||
1094 | |||
1095 | static int medummy_query_version_device_driver(me_device_t *device, | ||
1096 | int *version) | ||
1097 | { | ||
1098 | PDEBUG("executed.\n"); | ||
1099 | |||
1100 | *version = ME_VERSION_DRIVER; | ||
1101 | return ME_ERRNO_SUCCESS; | ||
1102 | } | ||
1103 | |||
1104 | static void medummy_destructor(me_device_t *device) | ||
1105 | { | ||
1106 | PDEBUG("executed.\n"); | ||
1107 | kfree(device); | ||
1108 | } | ||
1109 | |||
1110 | static int init_device_info(unsigned short vendor_id, | ||
1111 | unsigned short device_id, | ||
1112 | unsigned int serial_no, | ||
1113 | int bus_type, | ||
1114 | int bus_no, | ||
1115 | int dev_no, | ||
1116 | int func_no, medummy_device_t *instance) | ||
1117 | { | ||
1118 | PDEBUG("executed.\n"); | ||
1119 | |||
1120 | // instance->magic = MEDUMMY_MAGIC_NUMBER; | ||
1121 | instance->vendor_id = vendor_id; | ||
1122 | instance->device_id = device_id; | ||
1123 | instance->serial_no = serial_no; | ||
1124 | instance->bus_type = bus_type; | ||
1125 | instance->bus_no = bus_no; | ||
1126 | instance->dev_no = dev_no; | ||
1127 | instance->func_no = func_no; | ||
1128 | |||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1132 | static int medummy_config_load(me_device_t *device, struct file *filep, | ||
1133 | me_cfg_device_entry_t *config) | ||
1134 | { | ||
1135 | PDEBUG("executed.\n"); | ||
1136 | return ME_ERRNO_SUCCESS; | ||
1137 | } | ||
1138 | |||
1139 | static int init_device_instance(me_device_t *device) | ||
1140 | { | ||
1141 | PDEBUG("executed.\n"); | ||
1142 | |||
1143 | INIT_LIST_HEAD(&device->list); | ||
1144 | |||
1145 | device->me_device_io_irq_start = medummy_io_irq_start; | ||
1146 | device->me_device_io_irq_wait = medummy_io_irq_wait; | ||
1147 | device->me_device_io_irq_stop = medummy_io_irq_stop; | ||
1148 | device->me_device_io_reset_device = medummy_io_reset_device; | ||
1149 | device->me_device_io_reset_subdevice = medummy_io_reset_subdevice; | ||
1150 | device->me_device_io_single_config = medummy_io_single_config; | ||
1151 | device->me_device_io_single_read = medummy_io_single_read; | ||
1152 | device->me_device_io_single_write = medummy_io_single_write; | ||
1153 | device->me_device_io_stream_config = medummy_io_stream_config; | ||
1154 | device->me_device_io_stream_new_values = medummy_io_stream_new_values; | ||
1155 | device->me_device_io_stream_read = medummy_io_stream_read; | ||
1156 | device->me_device_io_stream_start = medummy_io_stream_start; | ||
1157 | device->me_device_io_stream_status = medummy_io_stream_status; | ||
1158 | device->me_device_io_stream_stop = medummy_io_stream_stop; | ||
1159 | device->me_device_io_stream_write = medummy_io_stream_write; | ||
1160 | |||
1161 | device->me_device_lock_device = medummy_lock_device; | ||
1162 | device->me_device_lock_subdevice = medummy_lock_subdevice; | ||
1163 | |||
1164 | device->me_device_query_description_device = | ||
1165 | medummy_query_description_device; | ||
1166 | device->me_device_query_info_device = medummy_query_info_device; | ||
1167 | device->me_device_query_name_device_driver = | ||
1168 | medummy_query_name_device_driver; | ||
1169 | device->me_device_query_name_device = medummy_query_name_device; | ||
1170 | |||
1171 | device->me_device_query_number_subdevices = | ||
1172 | medummy_query_number_subdevices; | ||
1173 | device->me_device_query_number_channels = medummy_query_number_channels; | ||
1174 | device->me_device_query_number_ranges = medummy_query_number_ranges; | ||
1175 | |||
1176 | device->me_device_query_range_by_min_max = | ||
1177 | medummy_query_range_by_min_max; | ||
1178 | device->me_device_query_range_info = medummy_query_range_info; | ||
1179 | |||
1180 | device->me_device_query_subdevice_type = medummy_query_subdevice_type; | ||
1181 | device->me_device_query_subdevice_by_type = | ||
1182 | medummy_query_subdevice_by_type; | ||
1183 | device->me_device_query_subdevice_caps = medummy_query_subdevice_caps; | ||
1184 | device->me_device_query_subdevice_caps_args = | ||
1185 | medummy_query_subdevice_caps_args; | ||
1186 | |||
1187 | device->me_device_query_timer = medummy_query_timer; | ||
1188 | |||
1189 | device->me_device_query_version_device_driver = | ||
1190 | medummy_query_version_device_driver; | ||
1191 | |||
1192 | device->me_device_destructor = medummy_destructor; | ||
1193 | device->me_device_config_load = medummy_config_load; | ||
1194 | return 0; | ||
1195 | } | ||
1196 | |||
1197 | me_device_t *medummy_constructor(unsigned short vendor_id, | ||
1198 | unsigned short device_id, | ||
1199 | unsigned int serial_no, | ||
1200 | int bus_type, | ||
1201 | int bus_no, int dev_no, int func_no) | ||
1202 | { | ||
1203 | int result = 0; | ||
1204 | medummy_device_t *instance; | ||
1205 | |||
1206 | PDEBUG("executed.\n"); | ||
1207 | |||
1208 | /* Allocate structure for device attributes */ | ||
1209 | instance = kmalloc(sizeof(medummy_device_t), GFP_KERNEL); | ||
1210 | |||
1211 | if (!instance) { | ||
1212 | PERROR("Can't get memory for device instance.\n"); | ||
1213 | return NULL; | ||
1214 | } | ||
1215 | |||
1216 | memset(instance, 0, sizeof(medummy_device_t)); | ||
1217 | |||
1218 | /* Initialize device info */ | ||
1219 | result = init_device_info(vendor_id, | ||
1220 | device_id, | ||
1221 | serial_no, | ||
1222 | bus_type, bus_no, dev_no, func_no, instance); | ||
1223 | |||
1224 | if (result) { | ||
1225 | PERROR("Cannot init baord info.\n"); | ||
1226 | kfree(instance); | ||
1227 | return NULL; | ||
1228 | } | ||
1229 | |||
1230 | /* Initialize device instance */ | ||
1231 | result = init_device_instance((me_device_t *) instance); | ||
1232 | |||
1233 | if (result) { | ||
1234 | PERROR("Cannot init baord info.\n"); | ||
1235 | kfree(instance); | ||
1236 | return NULL; | ||
1237 | } | ||
1238 | |||
1239 | return (me_device_t *) instance; | ||
1240 | } | ||
1241 | EXPORT_SYMBOL(medummy_constructor); | ||
1242 | |||
1243 | // Init and exit of module. | ||
1244 | |||
1245 | static int __init dummy_init(void) | ||
1246 | { | ||
1247 | PDEBUG("executed.\n"); | ||
1248 | return 0; | ||
1249 | } | ||
1250 | |||
1251 | static void __exit dummy_exit(void) | ||
1252 | { | ||
1253 | PDEBUG("executed.\n"); | ||
1254 | } | ||
1255 | |||
1256 | module_init(dummy_init); | ||
1257 | |||
1258 | module_exit(dummy_exit); | ||
1259 | |||
1260 | // Administrative stuff for modinfo. | ||
1261 | MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>"); | ||
1262 | MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-DUMMY Devices"); | ||
1263 | MODULE_SUPPORTED_DEVICE("Meilhaus ME-DUMMY Devices"); | ||
1264 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/medummy.h b/drivers/staging/meilhaus/medummy.h deleted file mode 100644 index 717000ff6c1c..000000000000 --- a/drivers/staging/meilhaus/medummy.h +++ /dev/null | |||
@@ -1,40 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : medummy.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | */ | ||
7 | |||
8 | #ifndef _MEDUMMY_H_ | ||
9 | #define _MEDUMMY_H_ | ||
10 | |||
11 | #include "metypes.h" | ||
12 | #include "medefines.h" | ||
13 | #include "medevice.h" | ||
14 | |||
15 | #ifdef __KERNEL__ | ||
16 | |||
17 | #define MEDUMMY_MAGIC_NUMBER 0xDDDD | ||
18 | |||
19 | typedef struct medummy_device { | ||
20 | me_device_t base; /**< The Meilhaus device base class. */ | ||
21 | // int magic; /**< The magic number of the structure */ | ||
22 | unsigned short vendor_id; /**< Vendor ID */ | ||
23 | unsigned short device_id; /**< Device ID */ | ||
24 | unsigned int serial_no; /**< Serial number of the device */ | ||
25 | int bus_type; /**< Bus type */ | ||
26 | int bus_no; /**< Bus number */ | ||
27 | int dev_no; /**< Device number */ | ||
28 | int func_no; /**< Function number */ | ||
29 | } medummy_device_t; | ||
30 | |||
31 | me_device_t *medummy_constructor(unsigned short vendor_id, | ||
32 | unsigned short device_id, | ||
33 | unsigned int serial_no, | ||
34 | int bus_type, | ||
35 | int bus_no, | ||
36 | int dev_no, | ||
37 | int func_no) __attribute__ ((weak)); | ||
38 | |||
39 | #endif | ||
40 | #endif | ||
diff --git a/drivers/staging/meilhaus/meerror.h b/drivers/staging/meilhaus/meerror.h deleted file mode 100644 index 9eda4bf907ba..000000000000 --- a/drivers/staging/meilhaus/meerror.h +++ /dev/null | |||
@@ -1,100 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : meerror.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | * Author : KG (Krzysztof Gantzke) <k.gantzke@meilhaus.de> | ||
7 | */ | ||
8 | |||
9 | #ifndef _MEERROR_H_ | ||
10 | #define _MEERROR_H_ | ||
11 | |||
12 | extern char *meErrorMsgTable[]; | ||
13 | |||
14 | #define ME_ERRNO_SUCCESS 0 | ||
15 | #define ME_ERRNO_INVALID_DEVICE 1 | ||
16 | #define ME_ERRNO_INVALID_SUBDEVICE 2 | ||
17 | #define ME_ERRNO_INVALID_CHANNEL 3 | ||
18 | #define ME_ERRNO_INVALID_SINGLE_CONFIG 4 | ||
19 | #define ME_ERRNO_INVALID_REF 5 | ||
20 | #define ME_ERRNO_INVALID_TRIG_CHAN 6 | ||
21 | #define ME_ERRNO_INVALID_TRIG_TYPE 7 | ||
22 | #define ME_ERRNO_INVALID_TRIG_EDGE 8 | ||
23 | #define ME_ERRNO_INVALID_TIMEOUT 9 | ||
24 | #define ME_ERRNO_INVALID_FLAGS 10 | ||
25 | #define ME_ERRNO_OPEN 11 | ||
26 | #define ME_ERRNO_CLOSE 12 | ||
27 | #define ME_ERRNO_NOT_OPEN 13 | ||
28 | #define ME_ERRNO_INVALID_DIR 14 | ||
29 | #define ME_ERRNO_PREVIOUS_CONFIG 15 | ||
30 | #define ME_ERRNO_NOT_SUPPORTED 16 | ||
31 | #define ME_ERRNO_SUBDEVICE_TYPE 17 | ||
32 | #define ME_ERRNO_USER_BUFFER_SIZE 18 | ||
33 | #define ME_ERRNO_LOCKED 19 | ||
34 | #define ME_ERRNO_NOMORE_SUBDEVICE_TYPE 20 | ||
35 | #define ME_ERRNO_TIMEOUT 21 | ||
36 | #define ME_ERRNO_SIGNAL 22 | ||
37 | #define ME_ERRNO_INVALID_IRQ_SOURCE 23 | ||
38 | #define ME_ERRNO_THREAD_RUNNING 24 | ||
39 | #define ME_ERRNO_START_THREAD 25 | ||
40 | #define ME_ERRNO_CANCEL_THREAD 26 | ||
41 | #define ME_ERRNO_NO_CALLBACK 27 | ||
42 | #define ME_ERRNO_USED 28 | ||
43 | #define ME_ERRNO_INVALID_UNIT 29 | ||
44 | #define ME_ERRNO_INVALID_MIN_MAX 30 | ||
45 | #define ME_ERRNO_NO_RANGE 31 | ||
46 | #define ME_ERRNO_INVALID_RANGE 32 | ||
47 | #define ME_ERRNO_SUBDEVICE_BUSY 33 | ||
48 | #define ME_ERRNO_INVALID_LOCK 34 | ||
49 | #define ME_ERRNO_INVALID_SWITCH 35 | ||
50 | #define ME_ERRNO_INVALID_ERROR_MSG_COUNT 36 | ||
51 | #define ME_ERRNO_INVALID_STREAM_CONFIG 37 | ||
52 | #define ME_ERRNO_INVALID_CONFIG_LIST_COUNT 38 | ||
53 | #define ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE 39 | ||
54 | #define ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE 40 | ||
55 | #define ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN 41 | ||
56 | #define ME_ERRNO_INVALID_ACQ_START_TIMEOUT 42 | ||
57 | #define ME_ERRNO_INVALID_ACQ_START_ARG 43 | ||
58 | #define ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE 44 | ||
59 | #define ME_ERRNO_INVALID_SCAN_START_ARG 45 | ||
60 | #define ME_ERRNO_INVALID_CONV_START_TRIG_TYPE 46 | ||
61 | #define ME_ERRNO_INVALID_CONV_START_ARG 47 | ||
62 | #define ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE 48 | ||
63 | #define ME_ERRNO_INVALID_SCAN_STOP_ARG 49 | ||
64 | #define ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE 50 | ||
65 | #define ME_ERRNO_INVALID_ACQ_STOP_ARG 51 | ||
66 | #define ME_ERRNO_SUBDEVICE_NOT_RUNNING 52 | ||
67 | #define ME_ERRNO_INVALID_READ_MODE 53 | ||
68 | #define ME_ERRNO_INVALID_VALUE_COUNT 54 | ||
69 | #define ME_ERRNO_INVALID_WRITE_MODE 55 | ||
70 | #define ME_ERRNO_INVALID_TIMER 56 | ||
71 | #define ME_ERRNO_DEVICE_UNPLUGGED 57 | ||
72 | #define ME_ERRNO_USED_INTERNAL 58 | ||
73 | #define ME_ERRNO_INVALID_DUTY_CYCLE 59 | ||
74 | #define ME_ERRNO_INVALID_WAIT 60 | ||
75 | #define ME_ERRNO_CONNECT_REMOTE 61 | ||
76 | #define ME_ERRNO_COMMUNICATION 62 | ||
77 | #define ME_ERRNO_INVALID_SINGLE_LIST 63 | ||
78 | #define ME_ERRNO_INVALID_MODULE_TYPE 64 | ||
79 | #define ME_ERRNO_INVALID_START_MODE 65 | ||
80 | #define ME_ERRNO_INVALID_STOP_MODE 66 | ||
81 | #define ME_ERRNO_INVALID_FIFO_IRQ_THRESHOLD 67 | ||
82 | #define ME_ERRNO_INVALID_POINTER 68 | ||
83 | #define ME_ERRNO_CREATE_EVENT 69 | ||
84 | #define ME_ERRNO_LACK_OF_RESOURCES 70 | ||
85 | #define ME_ERRNO_CANCELLED 71 | ||
86 | #define ME_ERRNO_RING_BUFFER_OVERFLOW 72 | ||
87 | #define ME_ERRNO_RING_BUFFER_UNDEFFLOW 73 | ||
88 | #define ME_ERRNO_INVALID_IRQ_EDGE 74 | ||
89 | #define ME_ERRNO_INVALID_IRQ_ARG 75 | ||
90 | #define ME_ERRNO_INVALID_CAP 76 | ||
91 | #define ME_ERRNO_INVALID_CAP_ARG_COUNT 77 | ||
92 | #define ME_ERRNO_INTERNAL 78 | ||
93 | |||
94 | /** New error for range check */ | ||
95 | #define ME_ERRNO_VALUE_OUT_OF_RANGE 79 | ||
96 | #define ME_ERRNO_FIFO_BUFFER_OVERFLOW 80 | ||
97 | #define ME_ERRNO_FIFO_BUFFER_UNDEFFLOW 81 | ||
98 | |||
99 | #define ME_ERRNO_INVALID_ERROR_NUMBER 82 | ||
100 | #endif | ||
diff --git a/drivers/staging/meilhaus/mefirmware.c b/drivers/staging/meilhaus/mefirmware.c deleted file mode 100644 index c07d202e8cb5..000000000000 --- a/drivers/staging/meilhaus/mefirmware.c +++ /dev/null | |||
@@ -1,137 +0,0 @@ | |||
1 | /** | ||
2 | * @file mefirmware.c | ||
3 | * | ||
4 | * @brief Implements the firmware handling. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /*************************************************************************** | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) * | ||
12 | * Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de * | ||
13 | * * | ||
14 | * This program is free software; you can redistribute it and/or modify * | ||
15 | * it under the terms of the GNU General Public License as published by * | ||
16 | * the Free Software Foundation; either version 2 of the License, or * | ||
17 | * (at your option) any later version. * | ||
18 | * * | ||
19 | * This program is distributed in the hope that it will be useful, * | ||
20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
22 | * GNU General Public License for more details. * | ||
23 | * * | ||
24 | * You should have received a copy of the GNU General Public License * | ||
25 | * along with this program; if not, write to the * | ||
26 | * Free Software Foundation, Inc., * | ||
27 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
28 | ***************************************************************************/ | ||
29 | |||
30 | #ifndef __KERNEL__ | ||
31 | # define __KERNEL__ | ||
32 | #endif | ||
33 | |||
34 | #ifndef KBUILD_MODNAME | ||
35 | # define KBUILD_MODNAME KBUILD_STR(mefirmware) | ||
36 | #endif | ||
37 | |||
38 | #include <linux/pci.h> | ||
39 | #include <linux/delay.h> | ||
40 | |||
41 | #include <linux/firmware.h> | ||
42 | |||
43 | #include "meplx_reg.h" | ||
44 | #include "medebug.h" | ||
45 | |||
46 | #include "mefirmware.h" | ||
47 | |||
48 | int me_xilinx_download(unsigned long register_base_control, | ||
49 | unsigned long register_base_data, | ||
50 | struct device *dev, const char *firmware_name) | ||
51 | { | ||
52 | int err = ME_ERRNO_FIRMWARE; | ||
53 | uint32_t value = 0; | ||
54 | int idx = 0; | ||
55 | |||
56 | const struct firmware *fw; | ||
57 | |||
58 | PDEBUG("executed.\n"); | ||
59 | |||
60 | if (!firmware_name) { | ||
61 | PERROR("Request for firmware failed. No name provided. \n"); | ||
62 | return err; | ||
63 | } | ||
64 | |||
65 | PINFO("Request '%s' firmware.\n", firmware_name); | ||
66 | err = request_firmware(&fw, firmware_name, dev); | ||
67 | |||
68 | if (err) { | ||
69 | PERROR("Request for firmware failed.\n"); | ||
70 | return err; | ||
71 | } | ||
72 | // Set PLX local interrupt 2 polarity to high. | ||
73 | // Interrupt is thrown by init pin of xilinx. | ||
74 | outl(PLX_INTCSR_LOCAL_INT2_POL, register_base_control + PLX_INTCSR); | ||
75 | |||
76 | // Set /CS and /WRITE of the Xilinx | ||
77 | value = inl(register_base_control + PLX_ICR); | ||
78 | value |= ME_FIRMWARE_CS_WRITE; | ||
79 | outl(value, register_base_control + PLX_ICR); | ||
80 | |||
81 | // Init Xilinx with CS1 | ||
82 | inl(register_base_data + ME_XILINX_CS1_REG); | ||
83 | |||
84 | // Wait for init to complete | ||
85 | udelay(20); | ||
86 | |||
87 | // Checkl /INIT pin | ||
88 | if (! | ||
89 | (inl(register_base_control + PLX_INTCSR) & | ||
90 | PLX_INTCSR_LOCAL_INT2_STATE)) { | ||
91 | PERROR("Can't init Xilinx.\n"); | ||
92 | release_firmware(fw); | ||
93 | return -EIO; | ||
94 | } | ||
95 | // Reset /CS and /WRITE of the Xilinx | ||
96 | value = inl(register_base_control + PLX_ICR); | ||
97 | value &= ~ME_FIRMWARE_CS_WRITE; | ||
98 | outl(value, register_base_control + PLX_ICR); | ||
99 | |||
100 | // Download Xilinx firmware | ||
101 | udelay(10); | ||
102 | |||
103 | for (idx = 0; idx < fw->size; idx++) { | ||
104 | outl(fw->data[idx], register_base_data); | ||
105 | #ifdef ME6000_v2_4 | ||
106 | /// This checking only for board's version 2.4 | ||
107 | // Check if BUSY flag is set (low = ready, high = busy) | ||
108 | if (inl(register_base_control + PLX_ICR) & | ||
109 | ME_FIRMWARE_BUSY_FLAG) { | ||
110 | PERROR("Xilinx is still busy (idx = %d)\n", idx); | ||
111 | release_firmware(fw); | ||
112 | return -EIO; | ||
113 | } | ||
114 | #endif //ME6000_v2_4 | ||
115 | } | ||
116 | PDEBUG("Download finished. %d bytes written to PLX.\n", idx); | ||
117 | |||
118 | // If done flag is high download was successful | ||
119 | if (inl(register_base_control + PLX_ICR) & ME_FIRMWARE_DONE_FLAG) { | ||
120 | PDEBUG("SUCCESS. Done flag is set.\n"); | ||
121 | } else { | ||
122 | PERROR("FAILURE. DONE flag is not set.\n"); | ||
123 | release_firmware(fw); | ||
124 | return -EIO; | ||
125 | } | ||
126 | |||
127 | // Set /CS and /WRITE | ||
128 | value = inl(register_base_control + PLX_ICR); | ||
129 | value |= ME_FIRMWARE_CS_WRITE; | ||
130 | outl(value, register_base_control + PLX_ICR); | ||
131 | |||
132 | PDEBUG("Enable interrupts on the PCI interface.\n"); | ||
133 | outl(ME_PLX_PCI_ACTIVATE, register_base_control + PLX_INTCSR); | ||
134 | release_firmware(fw); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
diff --git a/drivers/staging/meilhaus/mefirmware.h b/drivers/staging/meilhaus/mefirmware.h deleted file mode 100644 index a2685080c97b..000000000000 --- a/drivers/staging/meilhaus/mefirmware.h +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | /** | ||
2 | * @file mefirmware.h | ||
3 | * | ||
4 | * @brief Definitions of the firmware handling functions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
7 | */ | ||
8 | |||
9 | /*************************************************************************** | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) * | ||
11 | * Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de * | ||
12 | * * | ||
13 | * This program is free software; you can redistribute it and/or modify * | ||
14 | * it under the terms of the GNU General Public License as published by * | ||
15 | * the Free Software Foundation; either version 2 of the License, or * | ||
16 | * (at your option) any later version. * | ||
17 | * * | ||
18 | * This program is distributed in the hope that it will be useful, * | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
21 | * GNU General Public License for more details. * | ||
22 | * * | ||
23 | * You should have received a copy of the GNU General Public License * | ||
24 | * along with this program; if not, write to the * | ||
25 | * Free Software Foundation, Inc., * | ||
26 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | ||
27 | ***************************************************************************/ | ||
28 | |||
29 | #ifndef _MEFIRMWARE_H | ||
30 | # define _MEFIRMWARE_H | ||
31 | |||
32 | # ifdef __KERNEL__ | ||
33 | |||
34 | #define ME_ERRNO_FIRMWARE -1 | ||
35 | |||
36 | /** | ||
37 | * Registry | ||
38 | */ | ||
39 | #define ME_XILINX_CS1_REG 0x00C8 | ||
40 | |||
41 | /** | ||
42 | * Flags (bits) | ||
43 | */ | ||
44 | |||
45 | #define ME_FIRMWARE_BUSY_FLAG 0x00000020 | ||
46 | #define ME_FIRMWARE_DONE_FLAG 0x00000004 | ||
47 | #define ME_FIRMWARE_CS_WRITE 0x00000100 | ||
48 | |||
49 | #define ME_PLX_PCI_ACTIVATE 0x43 | ||
50 | |||
51 | int me_xilinx_download(unsigned long register_base_control, | ||
52 | unsigned long register_base_data, | ||
53 | struct device *dev, const char *firmware_name); | ||
54 | |||
55 | # endif //__KERNEL__ | ||
56 | |||
57 | #endif //_MEFIRMWARE_H | ||
diff --git a/drivers/staging/meilhaus/meids.h b/drivers/staging/meilhaus/meids.h deleted file mode 100644 index b3e757cbdda6..000000000000 --- a/drivers/staging/meilhaus/meids.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : meids.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | */ | ||
7 | |||
8 | #ifndef _MEIDS_H_ | ||
9 | #define _MEIDS_H_ | ||
10 | |||
11 | #ifdef __KERNEL__ | ||
12 | |||
13 | /*============================================================================= | ||
14 | Driver names | ||
15 | ===========================================================================*/ | ||
16 | |||
17 | #define MEMAIN_NAME "memain" | ||
18 | #define ME1000_NAME "me1000" | ||
19 | #define ME1400_NAME "me1400" | ||
20 | #define ME1600_NAME "me1600" | ||
21 | #define ME4600_NAME "me4600" | ||
22 | #define ME6000_NAME "me6000" | ||
23 | #define ME0600_NAME "me0600" //"me630" | ||
24 | #define ME8100_NAME "me8100" | ||
25 | #define ME8200_NAME "me8200" | ||
26 | #define ME0900_NAME "me0900" //"me9x" | ||
27 | //#define MEPHISTO_S1_NAME "mephisto_s1" | ||
28 | #define MEDUMMY_NAME "medummy" | ||
29 | |||
30 | #endif | ||
31 | #endif | ||
diff --git a/drivers/staging/meilhaus/meinternal.h b/drivers/staging/meilhaus/meinternal.h deleted file mode 100644 index 8d126b4905a7..000000000000 --- a/drivers/staging/meilhaus/meinternal.h +++ /dev/null | |||
@@ -1,363 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : meinternal.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | */ | ||
7 | |||
8 | #ifndef _MEINTERNAL_H_ | ||
9 | #define _MEINTERNAL_H_ | ||
10 | |||
11 | /*============================================================================= | ||
12 | PCI Vendor IDs | ||
13 | ===========================================================================*/ | ||
14 | |||
15 | #define PCI_VENDOR_ID_MEILHAUS 0x1402 | ||
16 | |||
17 | /*============================================================================= | ||
18 | PCI Device IDs | ||
19 | ===========================================================================*/ | ||
20 | |||
21 | #define PCI_DEVICE_ID_MEILHAUS_ME1000 0x1000 | ||
22 | #define PCI_DEVICE_ID_MEILHAUS_ME1000_A 0x100A | ||
23 | #define PCI_DEVICE_ID_MEILHAUS_ME1000_B 0x100B | ||
24 | |||
25 | #define PCI_DEVICE_ID_MEILHAUS_ME1400 0x1400 | ||
26 | #define PCI_DEVICE_ID_MEILHAUS_ME140A 0x140A | ||
27 | #define PCI_DEVICE_ID_MEILHAUS_ME140B 0x140B | ||
28 | #define PCI_DEVICE_ID_MEILHAUS_ME14E0 0x14E0 | ||
29 | #define PCI_DEVICE_ID_MEILHAUS_ME14EA 0x14EA | ||
30 | #define PCI_DEVICE_ID_MEILHAUS_ME14EB 0x14EB | ||
31 | #define PCI_DEVICE_ID_MEILHAUS_ME140C 0X140C | ||
32 | #define PCI_DEVICE_ID_MEILHAUS_ME140D 0X140D | ||
33 | |||
34 | #define PCI_DEVICE_ID_MEILHAUS_ME1600_4U 0x1604 // 4 voltage outputs | ||
35 | #define PCI_DEVICE_ID_MEILHAUS_ME1600_8U 0x1608 // 8 voltage outputs | ||
36 | #define PCI_DEVICE_ID_MEILHAUS_ME1600_12U 0x160C // 12 voltage outputs | ||
37 | #define PCI_DEVICE_ID_MEILHAUS_ME1600_16U 0x160F // 16 voltage outputs | ||
38 | #define PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I 0x168F // 16 voltage/8 current o. | ||
39 | |||
40 | #define PCI_DEVICE_ID_MEILHAUS_ME4610 0x4610 // Jekyll | ||
41 | |||
42 | #define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 // Low Cost version | ||
43 | |||
44 | #define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 // Standard version | ||
45 | #define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 // Isolated version | ||
46 | #define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 // Standard version with Sample and Hold | ||
47 | #define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 // Isolated version with Sample and Hold | ||
48 | |||
49 | #define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 // Standard version | ||
50 | #define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 // Isolated version | ||
51 | #define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 // Standard version with Sample and Hold | ||
52 | #define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 // Isolated version with Sample and Hold | ||
53 | |||
54 | #define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 // Standard version | ||
55 | #define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 // Isolated version | ||
56 | #define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 // Standard version with Sample and Hold | ||
57 | #define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 // Isolated version with Sample and Hold | ||
58 | |||
59 | /* ME6000 standard version */ | ||
60 | #define PCI_DEVICE_ID_MEILHAUS_ME6004 0x6004 | ||
61 | #define PCI_DEVICE_ID_MEILHAUS_ME6008 0x6008 | ||
62 | #define PCI_DEVICE_ID_MEILHAUS_ME600F 0x600F | ||
63 | |||
64 | /* ME6000 isolated version */ | ||
65 | #define PCI_DEVICE_ID_MEILHAUS_ME6014 0x6014 | ||
66 | #define PCI_DEVICE_ID_MEILHAUS_ME6018 0x6018 | ||
67 | #define PCI_DEVICE_ID_MEILHAUS_ME601F 0x601F | ||
68 | |||
69 | /* ME6000 isle version */ | ||
70 | #define PCI_DEVICE_ID_MEILHAUS_ME6034 0x6034 | ||
71 | #define PCI_DEVICE_ID_MEILHAUS_ME6038 0x6038 | ||
72 | #define PCI_DEVICE_ID_MEILHAUS_ME603F 0x603F | ||
73 | |||
74 | /* ME6000 standard version with DIO */ | ||
75 | #define PCI_DEVICE_ID_MEILHAUS_ME6044 0x6044 | ||
76 | #define PCI_DEVICE_ID_MEILHAUS_ME6048 0x6048 | ||
77 | #define PCI_DEVICE_ID_MEILHAUS_ME604F 0x604F | ||
78 | |||
79 | /* ME6000 isolated version with DIO */ | ||
80 | #define PCI_DEVICE_ID_MEILHAUS_ME6054 0x6054 | ||
81 | #define PCI_DEVICE_ID_MEILHAUS_ME6058 0x6058 | ||
82 | #define PCI_DEVICE_ID_MEILHAUS_ME605F 0x605F | ||
83 | |||
84 | /* ME6000 isle version with DIO */ | ||
85 | #define PCI_DEVICE_ID_MEILHAUS_ME6074 0x6074 | ||
86 | #define PCI_DEVICE_ID_MEILHAUS_ME6078 0x6078 | ||
87 | #define PCI_DEVICE_ID_MEILHAUS_ME607F 0x607F | ||
88 | |||
89 | /* ME6100 standard version */ | ||
90 | #define PCI_DEVICE_ID_MEILHAUS_ME6104 0x6104 | ||
91 | #define PCI_DEVICE_ID_MEILHAUS_ME6108 0x6108 | ||
92 | #define PCI_DEVICE_ID_MEILHAUS_ME610F 0x610F | ||
93 | |||
94 | /* ME6100 isolated version */ | ||
95 | #define PCI_DEVICE_ID_MEILHAUS_ME6114 0x6114 | ||
96 | #define PCI_DEVICE_ID_MEILHAUS_ME6118 0x6118 | ||
97 | #define PCI_DEVICE_ID_MEILHAUS_ME611F 0x611F | ||
98 | |||
99 | /* ME6100 isle version */ | ||
100 | #define PCI_DEVICE_ID_MEILHAUS_ME6134 0x6134 | ||
101 | #define PCI_DEVICE_ID_MEILHAUS_ME6138 0x6138 | ||
102 | #define PCI_DEVICE_ID_MEILHAUS_ME613F 0x613F | ||
103 | |||
104 | /* ME6100 standard version with DIO */ | ||
105 | #define PCI_DEVICE_ID_MEILHAUS_ME6144 0x6144 | ||
106 | #define PCI_DEVICE_ID_MEILHAUS_ME6148 0x6148 | ||
107 | #define PCI_DEVICE_ID_MEILHAUS_ME614F 0x614F | ||
108 | |||
109 | /* ME6100 isolated version with DIO */ | ||
110 | #define PCI_DEVICE_ID_MEILHAUS_ME6154 0x6154 | ||
111 | #define PCI_DEVICE_ID_MEILHAUS_ME6158 0x6158 | ||
112 | #define PCI_DEVICE_ID_MEILHAUS_ME615F 0x615F | ||
113 | |||
114 | /* ME6100 isle version with DIO */ | ||
115 | #define PCI_DEVICE_ID_MEILHAUS_ME6174 0x6174 | ||
116 | #define PCI_DEVICE_ID_MEILHAUS_ME6178 0x6178 | ||
117 | #define PCI_DEVICE_ID_MEILHAUS_ME617F 0x617F | ||
118 | |||
119 | /* ME6200 isolated version with DIO */ | ||
120 | #define PCI_DEVICE_ID_MEILHAUS_ME6259 0x6259 | ||
121 | |||
122 | /* ME6300 isolated version with DIO */ | ||
123 | #define PCI_DEVICE_ID_MEILHAUS_ME6359 0x6359 | ||
124 | |||
125 | /* ME0630 */ | ||
126 | #define PCI_DEVICE_ID_MEILHAUS_ME0630 0x0630 | ||
127 | |||
128 | /* ME8100 */ | ||
129 | #define PCI_DEVICE_ID_MEILHAUS_ME8100_A 0x810A | ||
130 | #define PCI_DEVICE_ID_MEILHAUS_ME8100_B 0x810B | ||
131 | |||
132 | /* ME8200 */ | ||
133 | #define PCI_DEVICE_ID_MEILHAUS_ME8200_A 0x820A | ||
134 | #define PCI_DEVICE_ID_MEILHAUS_ME8200_B 0x820B | ||
135 | |||
136 | /* ME0900 */ | ||
137 | #define PCI_DEVICE_ID_MEILHAUS_ME0940 0x0940 | ||
138 | #define PCI_DEVICE_ID_MEILHAUS_ME0950 0x0950 | ||
139 | #define PCI_DEVICE_ID_MEILHAUS_ME0960 0x0960 | ||
140 | |||
141 | |||
142 | /*============================================================================= | ||
143 | USB Vendor IDs | ||
144 | ===========================================================================*/ | ||
145 | |||
146 | //#define USB_VENDOR_ID_MEPHISTO_S1 0x0403 | ||
147 | |||
148 | |||
149 | /*============================================================================= | ||
150 | USB Device IDs | ||
151 | ===========================================================================*/ | ||
152 | |||
153 | //#define USB_DEVICE_ID_MEPHISTO_S1 0xDCD0 | ||
154 | |||
155 | |||
156 | /* ME-1000 defines */ | ||
157 | #define ME1000_NAME_DRIVER "ME-1000" | ||
158 | |||
159 | #define ME1000_NAME_DEVICE_ME1000 "ME-1000" | ||
160 | |||
161 | #define ME1000_DESCRIPTION_DEVICE_ME1000 "ME-1000 device, 128 digital i/o lines." | ||
162 | |||
163 | /* ME-1400 defines */ | ||
164 | #define ME1400_NAME_DRIVER "ME-1400" | ||
165 | |||
166 | #define ME1400_NAME_DEVICE_ME1400 "ME-1400" | ||
167 | #define ME1400_NAME_DEVICE_ME1400E "ME-1400E" | ||
168 | #define ME1400_NAME_DEVICE_ME1400A "ME-1400A" | ||
169 | #define ME1400_NAME_DEVICE_ME1400EA "ME-1400EA" | ||
170 | #define ME1400_NAME_DEVICE_ME1400B "ME-1400B" | ||
171 | #define ME1400_NAME_DEVICE_ME1400EB "ME-1400EB" | ||
172 | #define ME1400_NAME_DEVICE_ME1400C "ME-1400C" | ||
173 | #define ME1400_NAME_DEVICE_ME1400D "ME-1400D" | ||
174 | |||
175 | #define ME1400_DESCRIPTION_DEVICE_ME1400 "ME-1400 device, 24 digital i/o lines." | ||
176 | #define ME1400_DESCRIPTION_DEVICE_ME1400E "ME-1400E device, 24 digital i/o lines." | ||
177 | #define ME1400_DESCRIPTION_DEVICE_ME1400A "ME-1400A device, 24 digital i/o lines, 3 counters." | ||
178 | #define ME1400_DESCRIPTION_DEVICE_ME1400EA "ME-1400EA device, 24 digital i/o lines, 3 counters." | ||
179 | #define ME1400_DESCRIPTION_DEVICE_ME1400B "ME-1400B device, 48 digital i/o lines, 6 counters." | ||
180 | #define ME1400_DESCRIPTION_DEVICE_ME1400EB "ME-1400EB device, 48 digital i/o lines, 6 counters." | ||
181 | #define ME1400_DESCRIPTION_DEVICE_ME1400C "ME-1400C device, 24 digital i/o lines, 15 counters." | ||
182 | #define ME1400_DESCRIPTION_DEVICE_ME1400D "ME-1400D device, 48 digital i/o lines, 30 counters." | ||
183 | |||
184 | /* ME-1600 defines */ | ||
185 | #define ME1600_NAME_DRIVER "ME-1600" | ||
186 | |||
187 | #define ME1600_NAME_DEVICE_ME16004U "ME-1600/4U" | ||
188 | #define ME1600_NAME_DEVICE_ME16008U "ME-1600/8U" | ||
189 | #define ME1600_NAME_DEVICE_ME160012U "ME-1600/12U" | ||
190 | #define ME1600_NAME_DEVICE_ME160016U "ME-1600/16U" | ||
191 | #define ME1600_NAME_DEVICE_ME160016U8I "ME-1600/16U8I" | ||
192 | |||
193 | #define ME1600_DESCRIPTION_DEVICE_ME16004U "ME-1600/4U device, 4 voltage outputs." | ||
194 | #define ME1600_DESCRIPTION_DEVICE_ME16008U "ME-1600/8U device, 8 voltage outputs." | ||
195 | #define ME1600_DESCRIPTION_DEVICE_ME160012U "ME-1600/12U device, 12 voltage outputs." | ||
196 | #define ME1600_DESCRIPTION_DEVICE_ME160016U "ME-1600/16U device, 16 voltage outputs." | ||
197 | #define ME1600_DESCRIPTION_DEVICE_ME160016U8I "ME-1600/16U8I device, 16 voltage, 8 current outputs." | ||
198 | |||
199 | /* ME-4000 defines */ | ||
200 | #define ME4600_NAME_DRIVER "ME-4600" | ||
201 | |||
202 | #define ME4600_NAME_DEVICE_ME4610 "ME-4610" | ||
203 | #define ME4600_NAME_DEVICE_ME4650 "ME-4650" | ||
204 | #define ME4600_NAME_DEVICE_ME4660 "ME-4660" | ||
205 | #define ME4600_NAME_DEVICE_ME4660I "ME-4660I" | ||
206 | #define ME4600_NAME_DEVICE_ME4660S "ME-4660S" | ||
207 | #define ME4600_NAME_DEVICE_ME4660IS "ME-4660IS" | ||
208 | #define ME4600_NAME_DEVICE_ME4670 "ME-4670" | ||
209 | #define ME4600_NAME_DEVICE_ME4670I "ME-4670I" | ||
210 | #define ME4600_NAME_DEVICE_ME4670S "ME-4670S" | ||
211 | #define ME4600_NAME_DEVICE_ME4670IS "ME-4670IS" | ||
212 | #define ME4600_NAME_DEVICE_ME4680 "ME-4680" | ||
213 | #define ME4600_NAME_DEVICE_ME4680I "ME-4680I" | ||
214 | #define ME4600_NAME_DEVICE_ME4680S "ME-4680S" | ||
215 | #define ME4600_NAME_DEVICE_ME4680IS "ME-4680IS" | ||
216 | |||
217 | #define ME4600_DESCRIPTION_DEVICE_ME4610 "ME-4610 device, 16 streaming analog inputs, 32 digital i/o lines, 3 counters, 1 external interrupt." | ||
218 | #define ME4600_DESCRIPTION_DEVICE_ME4650 "ME-4650 device, 16 streaming analog inputs, 32 digital i/o lines, 1 external interrupt." | ||
219 | #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." | ||
220 | #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." | ||
221 | #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." | ||
222 | #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." | ||
223 | #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." | ||
224 | #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." | ||
225 | #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." | ||
226 | #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." | ||
227 | #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." | ||
228 | #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." | ||
229 | #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." | ||
230 | #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." | ||
231 | |||
232 | /* ME-6000 defines */ | ||
233 | #define ME6000_NAME_DRIVER "ME-6000" | ||
234 | |||
235 | #define ME6000_NAME_DEVICE_ME60004 "ME-6000/4" | ||
236 | #define ME6000_NAME_DEVICE_ME60008 "ME-6000/8" | ||
237 | #define ME6000_NAME_DEVICE_ME600016 "ME-6000/16" | ||
238 | #define ME6000_NAME_DEVICE_ME6000I4 "ME-6000I/4" | ||
239 | #define ME6000_NAME_DEVICE_ME6000I8 "ME-6000I/8" | ||
240 | #define ME6000_NAME_DEVICE_ME6000I16 "ME-6000I/16" | ||
241 | #define ME6000_NAME_DEVICE_ME6000ISLE4 "ME-6000ISLE/4" | ||
242 | #define ME6000_NAME_DEVICE_ME6000ISLE8 "ME-6000ISLE/8" | ||
243 | #define ME6000_NAME_DEVICE_ME6000ISLE16 "ME-6000ISLE/16" | ||
244 | #define ME6000_NAME_DEVICE_ME61004 "ME-6100/4" | ||
245 | #define ME6000_NAME_DEVICE_ME61008 "ME-6100/8" | ||
246 | #define ME6000_NAME_DEVICE_ME610016 "ME-6100/16" | ||
247 | #define ME6000_NAME_DEVICE_ME6100I4 "ME-6100I/4" | ||
248 | #define ME6000_NAME_DEVICE_ME6100I8 "ME-6100I/8" | ||
249 | #define ME6000_NAME_DEVICE_ME6100I16 "ME-6100I/16" | ||
250 | #define ME6000_NAME_DEVICE_ME6100ISLE4 "ME-6100ISLE/4" | ||
251 | #define ME6000_NAME_DEVICE_ME6100ISLE8 "ME-6100ISLE/8" | ||
252 | #define ME6000_NAME_DEVICE_ME6100ISLE16 "ME-6100ISLE/16" | ||
253 | #define ME6000_NAME_DEVICE_ME60004DIO "ME-6000/4/DIO" | ||
254 | #define ME6000_NAME_DEVICE_ME60008DIO "ME-6000/8/DIO" | ||
255 | #define ME6000_NAME_DEVICE_ME600016DIO "ME-6000/16/DIO" | ||
256 | #define ME6000_NAME_DEVICE_ME6000I4DIO "ME-6000I/4/DIO" | ||
257 | #define ME6000_NAME_DEVICE_ME6000I8DIO "ME-6000I/8/DIO" | ||
258 | #define ME6000_NAME_DEVICE_ME6000I16DIO "ME-6000I/16/DIO" | ||
259 | #define ME6000_NAME_DEVICE_ME6000ISLE4DIO "ME-6000ISLE/4/DIO" | ||
260 | #define ME6000_NAME_DEVICE_ME6000ISLE8DIO "ME-6000ISLE/8/DIO" | ||
261 | #define ME6000_NAME_DEVICE_ME6000ISLE16DIO "ME-6000ISLE/16/DIO" | ||
262 | #define ME6000_NAME_DEVICE_ME61004DIO "ME-6100/4/DIO" | ||
263 | #define ME6000_NAME_DEVICE_ME61008DIO "ME-6100/8/DIO" | ||
264 | #define ME6000_NAME_DEVICE_ME610016DIO "ME-6100/16/DIO" | ||
265 | #define ME6000_NAME_DEVICE_ME6100I4DIO "ME-6100I/4/DIO" | ||
266 | #define ME6000_NAME_DEVICE_ME6100I8DIO "ME-6100I/8/DIO" | ||
267 | #define ME6000_NAME_DEVICE_ME6100I16DIO "ME-6100I/16/DIO" | ||
268 | #define ME6000_NAME_DEVICE_ME6100ISLE4DIO "ME-6100ISLE/4/DIO" | ||
269 | #define ME6000_NAME_DEVICE_ME6100ISLE8DIO "ME-6100ISLE/8/DIO" | ||
270 | #define ME6000_NAME_DEVICE_ME6100ISLE16DIO "ME-6100ISLE/16/DIO" | ||
271 | #define ME6000_NAME_DEVICE_ME6200I9DIO "ME-6200I/9/DIO" | ||
272 | #define ME6000_NAME_DEVICE_ME6300I9DIO "ME-6300I/9/DIO" | ||
273 | |||
274 | #define ME6000_DESCRIPTION_DEVICE_ME60004 "ME-6000/4 device, 4 single analog outputs." | ||
275 | #define ME6000_DESCRIPTION_DEVICE_ME60008 "ME-6000/8 device, 8 single analog outputs" | ||
276 | #define ME6000_DESCRIPTION_DEVICE_ME600016 "ME-6000/16 device, 16 single analog outputs" | ||
277 | #define ME6000_DESCRIPTION_DEVICE_ME6000I4 "ME-6000I/4 isolated device, 4 single analog outputs" | ||
278 | #define ME6000_DESCRIPTION_DEVICE_ME6000I8 "ME-6000I/8 isolated device, 8 single analog outputs" | ||
279 | #define ME6000_DESCRIPTION_DEVICE_ME6000I16 "ME-6000I/16 isolated device, 16 single analog outputs" | ||
280 | #define ME6000_DESCRIPTION_DEVICE_ME6000ISLE4 "ME-6000ISLE/4 isle device, 4 single analog outputs" | ||
281 | #define ME6000_DESCRIPTION_DEVICE_ME6000ISLE8 "ME-6000ISLE/8 isle device, 8 single analog outputs" | ||
282 | #define ME6000_DESCRIPTION_DEVICE_ME6000ISLE16 "ME-6000ISLE/16 isle device, 16 single analog outputs" | ||
283 | #define ME6000_DESCRIPTION_DEVICE_ME61004 "ME-6100/4 device, 4 streaming analog outputs." | ||
284 | #define ME6000_DESCRIPTION_DEVICE_ME61008 "ME-6100/8 device, 4 streaming, 4 single analog outputs." | ||
285 | #define ME6000_DESCRIPTION_DEVICE_ME610016 "ME-6100/16 device, 4 streaming, 12 single analog outputs." | ||
286 | #define ME6000_DESCRIPTION_DEVICE_ME6100I4 "ME-6100I/4 isolated device, 4 streaming analog outputs." | ||
287 | #define ME6000_DESCRIPTION_DEVICE_ME6100I8 "ME-6100I/8 isolated device, 4 streaming, 4 single analog outputs." | ||
288 | #define ME6000_DESCRIPTION_DEVICE_ME6100I16 "ME-6100I/16 isolated device, 4 streaming, 12 single analog outputs." | ||
289 | #define ME6000_DESCRIPTION_DEVICE_ME6100ISLE4 "ME-6100ISLE/4 isle device, 4 streaming analog outputs." | ||
290 | #define ME6000_DESCRIPTION_DEVICE_ME6100ISLE8 "ME-6100ISLE/8 isle device, 4 streaming, 4 single analog outputs." | ||
291 | #define ME6000_DESCRIPTION_DEVICE_ME6100ISLE16 "ME-6100ISLE/16 isle device, 4 streaming, 12 single analog outputs." | ||
292 | #define ME6000_DESCRIPTION_DEVICE_ME60004DIO "ME-6000/4/DIO device, 4 single analog outputs, 16 digital i/o lines." | ||
293 | #define ME6000_DESCRIPTION_DEVICE_ME60008DIO "ME-6000/8/DIO device, 8 single analog outputs, 16 digital i/o lines." | ||
294 | #define ME6000_DESCRIPTION_DEVICE_ME600016DIO "ME-6000/16/DIO device, 8 single analog outputs, 16 digital i/o lines." | ||
295 | #define ME6000_DESCRIPTION_DEVICE_ME6000I4DIO "ME-6000I/4/DIO isolated device, 4 single analog outputs, 16 digital i/o lines." | ||
296 | #define ME6000_DESCRIPTION_DEVICE_ME6000I8DIO "ME-6000I/8/DIO isolated device, 8 single analog outputs, 16 digital i/o lines." | ||
297 | #define ME6000_DESCRIPTION_DEVICE_ME6000I16DIO "ME-6000I/16/DIO isolated device, 16 single analog outputs, 16 digital i/o lines." | ||
298 | #define ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO "ME-6000ISLE/4/DIO isle device, 4 single analog outputs, 16 digital i/o lines." | ||
299 | #define ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO "ME-6000ISLE/8/DIO isle device, 8 single analog outputs, 16 digital i/o lines." | ||
300 | #define ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO "ME-6000ISLE/16/DIO isle device, 16 single analog outputs, 16 digital i/o lines." | ||
301 | #define ME6000_DESCRIPTION_DEVICE_ME61004DIO "ME-6100/4/DIO device, 4 streaming analog outputs, 16 digital i/o lines." | ||
302 | #define ME6000_DESCRIPTION_DEVICE_ME61008DIO "ME-6100/8/DIO device, 4 streaming, 4 single analog outputs, 16 digital i/o lines." | ||
303 | #define ME6000_DESCRIPTION_DEVICE_ME610016DIO "ME-6100/16/DIO device, 4 streaming, 12 single analog outputs, 16 digital i/o lines." | ||
304 | #define ME6000_DESCRIPTION_DEVICE_ME6100I4DIO "ME-6100I/4/DIO isolated device, 4 streaming analog outputs, 16 digital i/o lines." | ||
305 | #define ME6000_DESCRIPTION_DEVICE_ME6100I8DIO "ME-6100I/8/DIO isolated device, 4 streaming, 4 single analog outputs, 16 digital i/o lines." | ||
306 | #define ME6000_DESCRIPTION_DEVICE_ME6100I16DIO "ME-6100I/16/DIO isolated device, 4 streaming, 12 single analog outputs, 16 digital i/o lines." | ||
307 | #define ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO "ME-6100ISLE/4/DIO isle device, 4 streaming analog outputs, 16 digital i/o lines." | ||
308 | #define ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO "ME-6100ISLE/8/DIO isle device, 4 streaming, 4 single analog outputs, 16 digital i/o lines." | ||
309 | #define ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO "ME-6100ISLE/16/DIO isle device, 4 streaming, 12 single analog outputs, 16 digital i/o lines." | ||
310 | #define ME6000_DESCRIPTION_DEVICE_ME6200I9DIO "ME-6200I/9/DIO isolated device, 9 single analog outputs, 16 digital i/o lines." | ||
311 | #define ME6000_DESCRIPTION_DEVICE_ME6300I9DIO "ME-6300I/9/DIO isolated device, 4 streaming, 5 single analog outputs, 16 digital i/o lines." | ||
312 | |||
313 | /* ME-630 defines */ | ||
314 | #define ME0600_NAME_DRIVER "ME-0600" | ||
315 | |||
316 | #define ME0600_NAME_DEVICE_ME0630 "ME-630" | ||
317 | |||
318 | #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." | ||
319 | |||
320 | /* ME-8100 defines */ | ||
321 | #define ME8100_NAME_DRIVER "ME-8100" | ||
322 | |||
323 | #define ME8100_NAME_DEVICE_ME8100A "ME-8100A" | ||
324 | #define ME8100_NAME_DEVICE_ME8100B "ME-8100B" | ||
325 | |||
326 | #define ME8100_DESCRIPTION_DEVICE_ME8100A "ME-8100A opto isolated device, 16 digital input lines, 16 digital output lines." | ||
327 | #define ME8100_DESCRIPTION_DEVICE_ME8100B "ME-8100B opto isolated device, 32 digital input lines, 32 digital output lines, 3 counters." | ||
328 | |||
329 | /* ME-8200 defines */ | ||
330 | #define ME8200_NAME_DRIVER "ME-8200" | ||
331 | |||
332 | #define ME8200_NAME_DEVICE_ME8200A "ME-8200A" | ||
333 | #define ME8200_NAME_DEVICE_ME8200B "ME-8200B" | ||
334 | |||
335 | #define ME8200_DESCRIPTION_DEVICE_ME8200A "ME-8200A opto isolated device, 8 digital output lines, 8 digital input lines, 16 digital i/o lines." | ||
336 | #define ME8200_DESCRIPTION_DEVICE_ME8200B "ME-8200B opto isolated device, 16 digital output lines, 16 digital input lines, 16 digital i/o lines." | ||
337 | |||
338 | /* ME-0900 defines */ | ||
339 | #define ME0900_NAME_DRIVER "ME-0900" | ||
340 | |||
341 | #define ME0900_NAME_DEVICE_ME0940 "ME-94" | ||
342 | #define ME0900_NAME_DEVICE_ME0950 "ME-95" | ||
343 | #define ME0900_NAME_DEVICE_ME0960 "ME-96" | ||
344 | |||
345 | #define ME0900_DESCRIPTION_DEVICE_ME0940 "ME-94 device, 16 digital input lines, 2 external interrupt lines." | ||
346 | #define ME0900_DESCRIPTION_DEVICE_ME0950 "ME-95 device, 16 digital output lines." | ||
347 | #define ME0900_DESCRIPTION_DEVICE_ME0960 "ME-96 device, 8 digital input lines, 8 digital output lines, 2 external interrupt lines." | ||
348 | |||
349 | /* ME-DUMMY defines */ | ||
350 | #define MEDUMMY_NAME_DRIVER "ME-Dummy" | ||
351 | |||
352 | /* MEPHISTO_S1 defines */ | ||
353 | /* | ||
354 | #define MEPHISTO_S1_NAME_DRIVER "MEphisto Scope 1" | ||
355 | #define MEPHISTO_S1_NAME_DEVICE "MEphisto Scope 1" | ||
356 | #define MEPHISTO_S1_DESCRIPTION_DEVICE "MEphisto Scope 1 device, 2 analog inputs, 24 digital i/o." | ||
357 | */ | ||
358 | /* Error defines */ | ||
359 | #define EMPTY_NAME_DRIVER "ME-???" | ||
360 | #define EMPTY_NAME_DEVICE "ME-???" | ||
361 | #define EMPTY_DESCRIPTION_DEVICE "ME-??? unknown device" | ||
362 | |||
363 | #endif | ||
diff --git a/drivers/staging/meilhaus/meioctl.h b/drivers/staging/meilhaus/meioctl.h deleted file mode 100644 index 6dc719fba57c..000000000000 --- a/drivers/staging/meilhaus/meioctl.h +++ /dev/null | |||
@@ -1,515 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : meioctl.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | */ | ||
7 | |||
8 | #ifndef _MEIOCTL_H_ | ||
9 | #define _MEIOCTL_H_ | ||
10 | |||
11 | |||
12 | /*============================================================================= | ||
13 | Types for the input/output ioctls | ||
14 | ===========================================================================*/ | ||
15 | |||
16 | typedef struct me_io_irq_start { | ||
17 | int device; | ||
18 | int subdevice; | ||
19 | int channel; | ||
20 | int irq_source; | ||
21 | int irq_edge; | ||
22 | int irq_arg; | ||
23 | int flags; | ||
24 | int errno; | ||
25 | } me_io_irq_start_t; | ||
26 | |||
27 | |||
28 | typedef struct me_io_irq_wait { | ||
29 | int device; | ||
30 | int subdevice; | ||
31 | int channel; | ||
32 | int irq_count; | ||
33 | int value; | ||
34 | int time_out; | ||
35 | int flags; | ||
36 | int errno; | ||
37 | } me_io_irq_wait_t; | ||
38 | |||
39 | |||
40 | typedef struct me_io_irq_stop { | ||
41 | int device; | ||
42 | int subdevice; | ||
43 | int channel; | ||
44 | int flags; | ||
45 | int errno; | ||
46 | } me_io_irq_stop_t; | ||
47 | |||
48 | |||
49 | typedef struct me_io_reset_device { | ||
50 | int device; | ||
51 | int flags; | ||
52 | int errno; | ||
53 | } me_io_reset_device_t; | ||
54 | |||
55 | |||
56 | typedef struct me_io_reset_subdevice { | ||
57 | int device; | ||
58 | int subdevice; | ||
59 | int flags; | ||
60 | int errno; | ||
61 | } me_io_reset_subdevice_t; | ||
62 | |||
63 | |||
64 | typedef struct me_io_single_config { | ||
65 | int device; | ||
66 | int subdevice; | ||
67 | int channel; | ||
68 | int single_config; | ||
69 | int ref; | ||
70 | int trig_chan; | ||
71 | int trig_type; | ||
72 | int trig_edge; | ||
73 | int flags; | ||
74 | int errno; | ||
75 | } me_io_single_config_t; | ||
76 | |||
77 | |||
78 | typedef struct me_io_single { | ||
79 | meIOSingle_t *single_list; | ||
80 | int count; | ||
81 | int flags; | ||
82 | int errno; | ||
83 | } me_io_single_t; | ||
84 | |||
85 | |||
86 | typedef struct me_io_stream_config { | ||
87 | int device; | ||
88 | int subdevice; | ||
89 | meIOStreamConfig_t *config_list; | ||
90 | int count; | ||
91 | meIOStreamTrigger_t trigger; | ||
92 | int fifo_irq_threshold; | ||
93 | int flags; | ||
94 | int errno; | ||
95 | } me_io_stream_config_t; | ||
96 | |||
97 | |||
98 | typedef struct me_io_stream_new_values { | ||
99 | int device; | ||
100 | int subdevice; | ||
101 | int time_out; | ||
102 | int count; | ||
103 | int flags; | ||
104 | int errno; | ||
105 | } me_io_stream_new_values_t; | ||
106 | |||
107 | |||
108 | typedef struct me_io_stream_read { | ||
109 | int device; | ||
110 | int subdevice; | ||
111 | int read_mode; | ||
112 | int *values; | ||
113 | int count; | ||
114 | int flags; | ||
115 | int errno; | ||
116 | } me_io_stream_read_t; | ||
117 | |||
118 | |||
119 | typedef struct me_io_stream_start { | ||
120 | meIOStreamStart_t *start_list; | ||
121 | int count; | ||
122 | int flags; | ||
123 | int errno; | ||
124 | } me_io_stream_start_t; | ||
125 | |||
126 | |||
127 | typedef struct me_io_stream_status { | ||
128 | int device; | ||
129 | int subdevice; | ||
130 | int wait; | ||
131 | int status; | ||
132 | int count; | ||
133 | int flags; | ||
134 | int errno; | ||
135 | } me_io_stream_status_t; | ||
136 | |||
137 | |||
138 | typedef struct me_io_stream_stop { | ||
139 | meIOStreamStop_t *stop_list; | ||
140 | int count; | ||
141 | int flags; | ||
142 | int errno; | ||
143 | } me_io_stream_stop_t; | ||
144 | |||
145 | |||
146 | typedef struct me_io_stream_write { | ||
147 | int device; | ||
148 | int subdevice; | ||
149 | int write_mode; | ||
150 | int *values; | ||
151 | int count; | ||
152 | int flags; | ||
153 | int errno; | ||
154 | } me_io_stream_write_t; | ||
155 | |||
156 | |||
157 | /*============================================================================= | ||
158 | Types for the lock ioctls | ||
159 | ===========================================================================*/ | ||
160 | |||
161 | typedef struct me_lock_device { | ||
162 | int device; | ||
163 | int lock; | ||
164 | int flags; | ||
165 | int errno; | ||
166 | } me_lock_device_t; | ||
167 | |||
168 | |||
169 | typedef struct me_lock_driver { | ||
170 | int flags; | ||
171 | int lock; | ||
172 | int errno; | ||
173 | } me_lock_driver_t; | ||
174 | |||
175 | |||
176 | typedef struct me_lock_subdevice { | ||
177 | int device; | ||
178 | int subdevice; | ||
179 | int lock; | ||
180 | int flags; | ||
181 | int errno; | ||
182 | } me_lock_subdevice_t; | ||
183 | |||
184 | |||
185 | /*============================================================================= | ||
186 | Types for the query ioctls | ||
187 | ===========================================================================*/ | ||
188 | |||
189 | typedef struct me_query_info_device { | ||
190 | int device; | ||
191 | int vendor_id; | ||
192 | int device_id; | ||
193 | int serial_no; | ||
194 | int bus_type; | ||
195 | int bus_no; | ||
196 | int dev_no; | ||
197 | int func_no; | ||
198 | int plugged; | ||
199 | int errno; | ||
200 | } me_query_info_device_t; | ||
201 | |||
202 | |||
203 | typedef struct me_query_description_device { | ||
204 | int device; | ||
205 | char *name; | ||
206 | int count; | ||
207 | int errno; | ||
208 | } me_query_description_device_t; | ||
209 | |||
210 | |||
211 | typedef struct me_query_name_device { | ||
212 | int device; | ||
213 | char *name; | ||
214 | int count; | ||
215 | int errno; | ||
216 | } me_query_name_device_t; | ||
217 | |||
218 | |||
219 | typedef struct me_query_name_device_driver { | ||
220 | int device; | ||
221 | char *name; | ||
222 | int count; | ||
223 | int errno; | ||
224 | } me_query_name_device_driver_t; | ||
225 | |||
226 | |||
227 | typedef struct me_query_version_main_driver { | ||
228 | int version; | ||
229 | int errno; | ||
230 | } me_query_version_main_driver_t; | ||
231 | |||
232 | |||
233 | typedef struct me_query_version_device_driver { | ||
234 | int device; | ||
235 | int version; | ||
236 | int errno; | ||
237 | } me_query_version_device_driver_t; | ||
238 | |||
239 | |||
240 | typedef struct me_query_number_devices { | ||
241 | int number; | ||
242 | int errno; | ||
243 | } me_query_number_devices_t; | ||
244 | |||
245 | |||
246 | typedef struct me_query_number_subdevices { | ||
247 | int device; | ||
248 | int number; | ||
249 | int errno; | ||
250 | } me_query_number_subdevices_t; | ||
251 | |||
252 | |||
253 | typedef struct me_query_number_channels { | ||
254 | int device; | ||
255 | int subdevice; | ||
256 | int number; | ||
257 | int errno; | ||
258 | } me_query_number_channels_t; | ||
259 | |||
260 | |||
261 | typedef struct me_query_number_ranges { | ||
262 | int device; | ||
263 | int subdevice; | ||
264 | int channel; | ||
265 | int unit; | ||
266 | int number; | ||
267 | int errno; | ||
268 | } me_query_number_ranges_t; | ||
269 | |||
270 | |||
271 | typedef struct me_query_subdevice_by_type { | ||
272 | int device; | ||
273 | int start_subdevice; | ||
274 | int type; | ||
275 | int subtype; | ||
276 | int subdevice; | ||
277 | int errno; | ||
278 | } me_query_subdevice_by_type_t; | ||
279 | |||
280 | |||
281 | typedef struct me_query_subdevice_type { | ||
282 | int device; | ||
283 | int subdevice; | ||
284 | int type; | ||
285 | int subtype; | ||
286 | int errno; | ||
287 | } me_query_subdevice_type_t; | ||
288 | |||
289 | |||
290 | typedef struct me_query_subdevice_caps { | ||
291 | int device; | ||
292 | int subdevice; | ||
293 | int caps; | ||
294 | int errno; | ||
295 | } me_query_subdevice_caps_t; | ||
296 | |||
297 | |||
298 | typedef struct me_query_subdevice_caps_args { | ||
299 | int device; | ||
300 | int subdevice; | ||
301 | int cap; | ||
302 | int args[8]; | ||
303 | int count; | ||
304 | int errno; | ||
305 | } me_query_subdevice_caps_args_t; | ||
306 | |||
307 | |||
308 | typedef struct me_query_timer { | ||
309 | int device; | ||
310 | int subdevice; | ||
311 | int timer; | ||
312 | int base_frequency; | ||
313 | long long min_ticks; | ||
314 | long long max_ticks; | ||
315 | int errno; | ||
316 | } me_query_timer_t; | ||
317 | |||
318 | |||
319 | typedef struct me_query_range_by_min_max { | ||
320 | int device; | ||
321 | int subdevice; | ||
322 | int channel; | ||
323 | int unit; | ||
324 | int min; | ||
325 | int max; | ||
326 | int max_data; | ||
327 | int range; | ||
328 | int errno; | ||
329 | } me_query_range_by_min_max_t; | ||
330 | |||
331 | |||
332 | typedef struct me_query_range_info { | ||
333 | int device; | ||
334 | int subdevice; | ||
335 | int channel; | ||
336 | int unit; | ||
337 | int range; | ||
338 | int min; | ||
339 | int max; | ||
340 | int max_data; | ||
341 | int errno; | ||
342 | } me_query_range_info_t; | ||
343 | |||
344 | |||
345 | /*============================================================================= | ||
346 | Types for the configuration ioctls | ||
347 | ===========================================================================*/ | ||
348 | |||
349 | typedef struct me_cfg_tcpip_location { | ||
350 | int access_type; | ||
351 | char *remote_host; | ||
352 | int remote_device_number; | ||
353 | } me_cfg_tcpip_location_t; | ||
354 | |||
355 | |||
356 | typedef union me_cfg_tcpip { | ||
357 | int access_type; | ||
358 | me_cfg_tcpip_location_t location; | ||
359 | } me_cfg_tcpip_t; | ||
360 | |||
361 | |||
362 | typedef struct me_cfg_pci_hw_location { | ||
363 | unsigned int bus_type; | ||
364 | unsigned int bus_no; | ||
365 | unsigned int device_no; | ||
366 | unsigned int function_no; | ||
367 | } me_cfg_pci_hw_location_t; | ||
368 | |||
369 | /* | ||
370 | typedef struct me_cfg_usb_hw_location { | ||
371 | unsigned int bus_type; | ||
372 | unsigned int root_hub_no; | ||
373 | } me_cfg_usb_hw_location_t; | ||
374 | */ | ||
375 | |||
376 | typedef union me_cfg_hw_location { | ||
377 | unsigned int bus_type; | ||
378 | me_cfg_pci_hw_location_t pci; | ||
379 | // me_cfg_usb_hw_location_t usb; | ||
380 | } me_cfg_hw_location_t; | ||
381 | |||
382 | |||
383 | typedef struct me_cfg_device_info { | ||
384 | unsigned int vendor_id; | ||
385 | unsigned int device_id; | ||
386 | unsigned int serial_no; | ||
387 | me_cfg_hw_location_t hw_location; | ||
388 | } me_cfg_device_info_t; | ||
389 | |||
390 | |||
391 | typedef struct me_cfg_subdevice_info { | ||
392 | int type; | ||
393 | int sub_type; | ||
394 | unsigned int number_channels; | ||
395 | } me_cfg_subdevice_info_t; | ||
396 | |||
397 | |||
398 | typedef struct me_cfg_range_entry { | ||
399 | int unit; | ||
400 | double min; | ||
401 | double max; | ||
402 | unsigned int max_data; | ||
403 | } me_cfg_range_entry_t; | ||
404 | |||
405 | |||
406 | typedef struct me_cfg_mux32m_device { | ||
407 | int type; | ||
408 | int timed; | ||
409 | unsigned int ai_channel; | ||
410 | unsigned int dio_device; | ||
411 | unsigned int dio_subdevice; | ||
412 | unsigned int timer_device; | ||
413 | unsigned int timer_subdevice; | ||
414 | unsigned int mux32s_count; | ||
415 | } me_cfg_mux32m_device_t; | ||
416 | |||
417 | |||
418 | typedef struct me_cfg_demux32_device { | ||
419 | int type; | ||
420 | int timed; | ||
421 | unsigned int ao_channel; | ||
422 | unsigned int dio_device; | ||
423 | unsigned int dio_subdevice; | ||
424 | unsigned int timer_device; | ||
425 | unsigned int timer_subdevice; | ||
426 | } me_cfg_demux32_device_t; | ||
427 | |||
428 | |||
429 | typedef union me_cfg_external_device { | ||
430 | int type; | ||
431 | me_cfg_mux32m_device_t mux32m; | ||
432 | me_cfg_demux32_device_t demux32; | ||
433 | } me_cfg_external_device_t; | ||
434 | |||
435 | |||
436 | typedef struct me_cfg_subdevice_entry { | ||
437 | me_cfg_subdevice_info_t info; | ||
438 | me_cfg_range_entry_t *range_list; | ||
439 | unsigned int count; | ||
440 | int locked; | ||
441 | me_cfg_external_device_t external_device; | ||
442 | } me_cfg_subdevice_entry_t; | ||
443 | |||
444 | |||
445 | typedef struct me_cfg_device_entry { | ||
446 | me_cfg_tcpip_t tcpip; | ||
447 | me_cfg_device_info_t info; | ||
448 | me_cfg_subdevice_entry_t *subdevice_list; | ||
449 | unsigned int count; | ||
450 | } me_cfg_device_entry_t; | ||
451 | |||
452 | |||
453 | typedef struct me_config_load { | ||
454 | me_cfg_device_entry_t *device_list; | ||
455 | unsigned int count; | ||
456 | int errno; | ||
457 | } me_config_load_t; | ||
458 | |||
459 | |||
460 | /*============================================================================= | ||
461 | The ioctls of the board | ||
462 | ===========================================================================*/ | ||
463 | |||
464 | #define MEMAIN_MAGIC 'y' | ||
465 | |||
466 | #define ME_IO_IRQ_ENABLE _IOR (MEMAIN_MAGIC, 1, me_io_irq_start_t) | ||
467 | #define ME_IO_IRQ_WAIT _IOR (MEMAIN_MAGIC, 2, me_io_irq_wait_t) | ||
468 | #define ME_IO_IRQ_DISABLE _IOR (MEMAIN_MAGIC, 3, me_io_irq_stop_t) | ||
469 | |||
470 | #define ME_IO_RESET_DEVICE _IOW (MEMAIN_MAGIC, 4, me_io_reset_device_t) | ||
471 | #define ME_IO_RESET_SUBDEVICE _IOW (MEMAIN_MAGIC, 5, me_io_reset_subdevice_t) | ||
472 | |||
473 | #define ME_IO_SINGLE _IOWR(MEMAIN_MAGIC, 6, me_io_single_t) | ||
474 | #define ME_IO_SINGLE_CONFIG _IOW (MEMAIN_MAGIC, 7, me_io_single_config_t) | ||
475 | |||
476 | #define ME_IO_STREAM_CONFIG _IOW (MEMAIN_MAGIC, 8, me_io_stream_config_t) | ||
477 | #define ME_IO_STREAM_NEW_VALUES _IOR (MEMAIN_MAGIC, 9, me_io_stream_new_values_t) | ||
478 | #define ME_IO_STREAM_READ _IOR (MEMAIN_MAGIC, 10, me_io_stream_read_t) | ||
479 | #define ME_IO_STREAM_START _IOW (MEMAIN_MAGIC, 11, me_io_stream_start_t) | ||
480 | #define ME_IO_STREAM_STATUS _IOR (MEMAIN_MAGIC, 12, me_io_stream_status_t) | ||
481 | #define ME_IO_STREAM_STOP _IOW (MEMAIN_MAGIC, 13, me_io_stream_stop_t) | ||
482 | #define ME_IO_STREAM_WRITE _IOW (MEMAIN_MAGIC, 14, me_io_stream_write_t) | ||
483 | |||
484 | #define ME_LOCK_DRIVER _IOW (MEMAIN_MAGIC, 15, me_lock_driver_t) | ||
485 | #define ME_LOCK_DEVICE _IOW (MEMAIN_MAGIC, 16, me_lock_device_t) | ||
486 | #define ME_LOCK_SUBDEVICE _IOW (MEMAIN_MAGIC, 17, me_lock_subdevice_t) | ||
487 | |||
488 | #define ME_QUERY_DESCRIPTION_DEVICE _IOR (MEMAIN_MAGIC, 18, me_query_description_device_t) | ||
489 | |||
490 | #define ME_QUERY_INFO_DEVICE _IOR (MEMAIN_MAGIC, 19, me_query_info_device_t) | ||
491 | |||
492 | #define ME_QUERY_NAME_DEVICE _IOR (MEMAIN_MAGIC, 20, me_query_name_device_t) | ||
493 | #define ME_QUERY_NAME_DEVICE_DRIVER _IOR (MEMAIN_MAGIC, 21, me_query_name_device_driver_t) | ||
494 | |||
495 | #define ME_QUERY_NUMBER_DEVICES _IOR (MEMAIN_MAGIC, 22, me_query_number_devices_t) | ||
496 | #define ME_QUERY_NUMBER_SUBDEVICES _IOR (MEMAIN_MAGIC, 23, me_query_number_subdevices_t) | ||
497 | #define ME_QUERY_NUMBER_CHANNELS _IOR (MEMAIN_MAGIC, 24, me_query_number_channels_t) | ||
498 | #define ME_QUERY_NUMBER_RANGES _IOR (MEMAIN_MAGIC, 25, me_query_number_ranges_t) | ||
499 | |||
500 | #define ME_QUERY_RANGE_BY_MIN_MAX _IOR (MEMAIN_MAGIC, 26, me_query_range_by_min_max_t) | ||
501 | #define ME_QUERY_RANGE_INFO _IOR (MEMAIN_MAGIC, 27, me_query_range_info_t) | ||
502 | |||
503 | #define ME_QUERY_SUBDEVICE_BY_TYPE _IOR (MEMAIN_MAGIC, 28, me_query_subdevice_by_type_t) | ||
504 | #define ME_QUERY_SUBDEVICE_TYPE _IOR (MEMAIN_MAGIC, 29, me_query_subdevice_type_t) | ||
505 | #define ME_QUERY_SUBDEVICE_CAPS _IOR (MEMAIN_MAGIC, 29, me_query_subdevice_caps_t) | ||
506 | #define ME_QUERY_SUBDEVICE_CAPS_ARGS _IOR (MEMAIN_MAGIC, 30, me_query_subdevice_caps_args_t) | ||
507 | |||
508 | #define ME_QUERY_TIMER _IOR (MEMAIN_MAGIC, 31, me_query_timer_t) | ||
509 | |||
510 | #define ME_QUERY_VERSION_DEVICE_DRIVER _IOR (MEMAIN_MAGIC, 32, me_query_version_device_driver_t) | ||
511 | #define ME_QUERY_VERSION_MAIN_DRIVER _IOR (MEMAIN_MAGIC, 33, me_query_version_main_driver_t) | ||
512 | |||
513 | #define ME_CONFIG_LOAD _IOWR(MEMAIN_MAGIC, 34, me_config_load_t) | ||
514 | |||
515 | #endif | ||
diff --git a/drivers/staging/meilhaus/memain.c b/drivers/staging/meilhaus/memain.c deleted file mode 100644 index c4908549192f..000000000000 --- a/drivers/staging/meilhaus/memain.c +++ /dev/null | |||
@@ -1,2084 +0,0 @@ | |||
1 | /** | ||
2 | * @file memain.c | ||
3 | * | ||
4 | * @brief Main Meilhaus device driver. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
12 | * | ||
13 | * This file is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License as published by | ||
15 | * the Free Software Foundation; either version 2 of the License, or | ||
16 | * (at your option) any later version. | ||
17 | * | ||
18 | * This program is distributed in the hope that it will be useful, | ||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
21 | * GNU General Public License for more details. | ||
22 | * | ||
23 | * You should have received a copy of the GNU General Public License | ||
24 | * along with this program; if not, write to the Free Software | ||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
26 | */ | ||
27 | |||
28 | #ifndef __KERNEL__ | ||
29 | # define __KERNEL__ | ||
30 | #endif | ||
31 | |||
32 | #ifndef MODULE | ||
33 | # define MODULE | ||
34 | #endif | ||
35 | |||
36 | #include <linux/module.h> | ||
37 | #include <linux/pci.h> | ||
38 | //#include <linux/usb.h> | ||
39 | #include <linux/errno.h> | ||
40 | #include <linux/uaccess.h> | ||
41 | #include <linux/miscdevice.h> | ||
42 | #include <linux/rwsem.h> | ||
43 | |||
44 | #include "medefines.h" | ||
45 | #include "metypes.h" | ||
46 | #include "meerror.h" | ||
47 | |||
48 | #include "medebug.h" | ||
49 | #include "memain.h" | ||
50 | #include "medevice.h" | ||
51 | #include "meioctl.h" | ||
52 | #include "mecommon.h" | ||
53 | |||
54 | /* Module parameters | ||
55 | */ | ||
56 | |||
57 | #ifdef BOSCH | ||
58 | static unsigned int me_bosch_fw = 0; | ||
59 | EXPORT_SYMBOL(me_bosch_fw); | ||
60 | |||
61 | # ifdef module_param | ||
62 | module_param(me_bosch_fw, int, S_IRUGO); | ||
63 | # else | ||
64 | MODULE_PARM(me_bosch_fw, "i"); | ||
65 | # endif | ||
66 | |||
67 | MODULE_PARM_DESC(me_bosch_fw, | ||
68 | "Flags which signals the ME-4600 driver to load the bosch firmware (default = 0)."); | ||
69 | #endif //BOSCH | ||
70 | |||
71 | /* Global Driver Lock | ||
72 | */ | ||
73 | |||
74 | static struct file *me_filep = NULL; | ||
75 | static int me_count = 0; | ||
76 | static DEFINE_SPINLOCK(me_lock); | ||
77 | static DECLARE_RWSEM(me_rwsem); | ||
78 | |||
79 | /* Board instances are kept in a global list */ | ||
80 | LIST_HEAD(me_device_list); | ||
81 | |||
82 | /* Prototypes | ||
83 | */ | ||
84 | |||
85 | static int me_probe_pci(struct pci_dev *dev, const struct pci_device_id *id); | ||
86 | static void me_remove_pci(struct pci_dev *dev); | ||
87 | static int insert_to_device_list(me_device_t *n_device); | ||
88 | static int replace_with_dummy(int vendor_id, int device_id, int serial_no); | ||
89 | static void clear_device_list(void); | ||
90 | static int me_open(struct inode *inode_ptr, struct file *filep); | ||
91 | static int me_release(struct inode *, struct file *); | ||
92 | static int me_ioctl(struct inode *, struct file *, unsigned int, unsigned long); | ||
93 | //static int me_probe_usb(struct usb_interface *interface, const struct usb_device_id *id); | ||
94 | //static void me_disconnect_usb(struct usb_interface *interface); | ||
95 | |||
96 | /* File operations provided by the module | ||
97 | */ | ||
98 | |||
99 | static const struct file_operations me_file_operations = { | ||
100 | .owner = THIS_MODULE, | ||
101 | .ioctl = me_ioctl, | ||
102 | .open = me_open, | ||
103 | .release = me_release, | ||
104 | }; | ||
105 | |||
106 | static const struct pci_device_id me_pci_table[] = { | ||
107 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000) }, | ||
108 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_A) }, | ||
109 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_B) }, | ||
110 | |||
111 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1400) }, | ||
112 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140A) }, | ||
113 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140B) }, | ||
114 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14E0) }, | ||
115 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EA) }, | ||
116 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EB) }, | ||
117 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140C) }, | ||
118 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140D) }, | ||
119 | |||
120 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_4U) }, | ||
121 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_8U) }, | ||
122 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_12U) }, | ||
123 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U) }, | ||
124 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I) }, | ||
125 | |||
126 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4610) }, | ||
127 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650) }, | ||
128 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660) }, | ||
129 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I) }, | ||
130 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670) }, | ||
131 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I) }, | ||
132 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S) }, | ||
133 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS) }, | ||
134 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680) }, | ||
135 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I) }, | ||
136 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S) }, | ||
137 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS) }, | ||
138 | |||
139 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6004) }, | ||
140 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6008) }, | ||
141 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME600F) }, | ||
142 | |||
143 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6014) }, | ||
144 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6018) }, | ||
145 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME601F) }, | ||
146 | |||
147 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6034) }, | ||
148 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6038) }, | ||
149 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME603F) }, | ||
150 | |||
151 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6104) }, | ||
152 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6108) }, | ||
153 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME610F) }, | ||
154 | |||
155 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6114) }, | ||
156 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6118) }, | ||
157 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME611F) }, | ||
158 | |||
159 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6134) }, | ||
160 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6138) }, | ||
161 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME613F) }, | ||
162 | |||
163 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6044) }, | ||
164 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6048) }, | ||
165 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME604F) }, | ||
166 | |||
167 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6054) }, | ||
168 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6058) }, | ||
169 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME605F) }, | ||
170 | |||
171 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6074) }, | ||
172 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6078) }, | ||
173 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME607F) }, | ||
174 | |||
175 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6144) }, | ||
176 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6148) }, | ||
177 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME614F) }, | ||
178 | |||
179 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6154) }, | ||
180 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6158) }, | ||
181 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME615F) }, | ||
182 | |||
183 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6174) }, | ||
184 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6178) }, | ||
185 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME617F) }, | ||
186 | |||
187 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6259) }, | ||
188 | |||
189 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6359) }, | ||
190 | |||
191 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0630) }, | ||
192 | |||
193 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_A) }, | ||
194 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_B) }, | ||
195 | |||
196 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_A) }, | ||
197 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_B) }, | ||
198 | |||
199 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0940) }, | ||
200 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0950) }, | ||
201 | { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0960) }, | ||
202 | |||
203 | { } | ||
204 | }; | ||
205 | MODULE_DEVICE_TABLE(pci, me_pci_table); | ||
206 | |||
207 | static struct pci_driver me_pci_driver = { | ||
208 | .name = MEMAIN_NAME, | ||
209 | .id_table = me_pci_table, | ||
210 | .probe = me_probe_pci, | ||
211 | .remove = __devexit_p(me_remove_pci), | ||
212 | }; | ||
213 | |||
214 | /* | ||
215 | static struct usb_device_id me_usb_table[] = { | ||
216 | { USB_DEVICE(USB_VENDOR_ID_MEPHISTO_S1, USB_DEVICE_ID_MEPHISTO_S1) }, | ||
217 | { 0 } | ||
218 | }; | ||
219 | MODULE_DEVICE_TABLE (usb, me_usb_table); | ||
220 | |||
221 | static struct usb_driver me_usb_driver = | ||
222 | { | ||
223 | .name = MEMAIN_NAME, | ||
224 | .id_table = me_usb_table, | ||
225 | .probe = me_probe_usb, | ||
226 | .disconnect = me_disconnect_usb | ||
227 | }; | ||
228 | */ | ||
229 | |||
230 | #ifdef ME_LOCK_MULTIPLEX_TEMPLATE | ||
231 | ME_LOCK_MULTIPLEX_TEMPLATE("me_lock_device", | ||
232 | me_lock_device_t, | ||
233 | me_lock_device, | ||
234 | me_device_lock_device, | ||
235 | (device, filep, karg.lock, karg.flags)) | ||
236 | |||
237 | ME_LOCK_MULTIPLEX_TEMPLATE("me_lock_subdevice", | ||
238 | me_lock_subdevice_t, | ||
239 | me_lock_subdevice, | ||
240 | me_device_lock_subdevice, | ||
241 | (device, filep, karg.subdevice, karg.lock, | ||
242 | karg.flags)) | ||
243 | #else | ||
244 | #error macro ME_LOCK_MULTIPLEX_TEMPLATE not defined | ||
245 | #endif | ||
246 | |||
247 | #ifdef ME_IO_MULTIPLEX_TEMPLATE | ||
248 | ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_start", | ||
249 | me_io_irq_start_t, | ||
250 | me_io_irq_start, | ||
251 | me_device_io_irq_start, | ||
252 | (device, | ||
253 | filep, | ||
254 | karg.subdevice, | ||
255 | karg.channel, | ||
256 | karg.irq_source, | ||
257 | karg.irq_edge, karg.irq_arg, karg.flags)) | ||
258 | |||
259 | ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_wait", | ||
260 | me_io_irq_wait_t, | ||
261 | me_io_irq_wait, | ||
262 | me_device_io_irq_wait, | ||
263 | (device, | ||
264 | filep, | ||
265 | karg.subdevice, | ||
266 | karg.channel, | ||
267 | &karg.irq_count, &karg.value, karg.time_out, karg.flags)) | ||
268 | |||
269 | ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_stop", | ||
270 | me_io_irq_stop_t, | ||
271 | me_io_irq_stop, | ||
272 | me_device_io_irq_stop, | ||
273 | (device, | ||
274 | filep, karg.subdevice, karg.channel, karg.flags)) | ||
275 | |||
276 | ME_IO_MULTIPLEX_TEMPLATE("me_io_reset_device", | ||
277 | me_io_reset_device_t, | ||
278 | me_io_reset_device, | ||
279 | me_device_io_reset_device, (device, filep, karg.flags)) | ||
280 | |||
281 | ME_IO_MULTIPLEX_TEMPLATE("me_io_reset_subdevice", | ||
282 | me_io_reset_subdevice_t, | ||
283 | me_io_reset_subdevice, | ||
284 | me_device_io_reset_subdevice, | ||
285 | (device, filep, karg.subdevice, karg.flags)) | ||
286 | |||
287 | ME_IO_MULTIPLEX_TEMPLATE("me_io_single_config", | ||
288 | me_io_single_config_t, | ||
289 | me_io_single_config, | ||
290 | me_device_io_single_config, | ||
291 | (device, | ||
292 | filep, | ||
293 | karg.subdevice, | ||
294 | karg.channel, | ||
295 | karg.single_config, | ||
296 | karg.ref, | ||
297 | karg.trig_chan, | ||
298 | karg.trig_type, karg.trig_edge, karg.flags)) | ||
299 | |||
300 | ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_new_values", | ||
301 | me_io_stream_new_values_t, | ||
302 | me_io_stream_new_values, | ||
303 | me_device_io_stream_new_values, | ||
304 | (device, | ||
305 | filep, | ||
306 | karg.subdevice, karg.time_out, &karg.count, karg.flags)) | ||
307 | |||
308 | ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_read", | ||
309 | me_io_stream_read_t, | ||
310 | me_io_stream_read, | ||
311 | me_device_io_stream_read, | ||
312 | (device, | ||
313 | filep, | ||
314 | karg.subdevice, | ||
315 | karg.read_mode, karg.values, &karg.count, karg.flags)) | ||
316 | |||
317 | ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_status", | ||
318 | me_io_stream_status_t, | ||
319 | me_io_stream_status, | ||
320 | me_device_io_stream_status, | ||
321 | (device, | ||
322 | filep, | ||
323 | karg.subdevice, | ||
324 | karg.wait, &karg.status, &karg.count, karg.flags)) | ||
325 | |||
326 | ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_write", | ||
327 | me_io_stream_write_t, | ||
328 | me_io_stream_write, | ||
329 | me_device_io_stream_write, | ||
330 | (device, | ||
331 | filep, | ||
332 | karg.subdevice, | ||
333 | karg.write_mode, karg.values, &karg.count, karg.flags)) | ||
334 | #else | ||
335 | #error macro ME_IO_MULTIPLEX_TEMPLATE not defined | ||
336 | #endif | ||
337 | |||
338 | #ifdef ME_QUERY_MULTIPLEX_STR_TEMPLATE | ||
339 | ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_name_device", | ||
340 | me_query_name_device_t, | ||
341 | me_query_name_device, | ||
342 | me_device_query_name_device, (device, &msg)) | ||
343 | |||
344 | ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_name_device_driver", | ||
345 | me_query_name_device_driver_t, | ||
346 | me_query_name_device_driver, | ||
347 | me_device_query_name_device_driver, | ||
348 | (device, &msg)) | ||
349 | |||
350 | ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_description_device", | ||
351 | me_query_description_device_t, | ||
352 | me_query_description_device, | ||
353 | me_device_query_description_device, | ||
354 | (device, &msg)) | ||
355 | #else | ||
356 | #error macro ME_QUERY_MULTIPLEX_STR_TEMPLATE not defined | ||
357 | #endif | ||
358 | |||
359 | #ifdef ME_QUERY_MULTIPLEX_TEMPLATE | ||
360 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_info_device", | ||
361 | me_query_info_device_t, | ||
362 | me_query_info_device, | ||
363 | me_device_query_info_device, | ||
364 | (device, | ||
365 | &karg.vendor_id, | ||
366 | &karg.device_id, | ||
367 | &karg.serial_no, | ||
368 | &karg.bus_type, | ||
369 | &karg.bus_no, | ||
370 | &karg.dev_no, &karg.func_no, &karg.plugged)) | ||
371 | |||
372 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_subdevices", | ||
373 | me_query_number_subdevices_t, | ||
374 | me_query_number_subdevices, | ||
375 | me_device_query_number_subdevices, | ||
376 | (device, &karg.number)) | ||
377 | |||
378 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_channels", | ||
379 | me_query_number_channels_t, | ||
380 | me_query_number_channels, | ||
381 | me_device_query_number_channels, | ||
382 | (device, karg.subdevice, &karg.number)) | ||
383 | |||
384 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_by_type", | ||
385 | me_query_subdevice_by_type_t, | ||
386 | me_query_subdevice_by_type, | ||
387 | me_device_query_subdevice_by_type, | ||
388 | (device, | ||
389 | karg.start_subdevice, | ||
390 | karg.type, karg.subtype, &karg.subdevice)) | ||
391 | |||
392 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_type", | ||
393 | me_query_subdevice_type_t, | ||
394 | me_query_subdevice_type, | ||
395 | me_device_query_subdevice_type, | ||
396 | (device, karg.subdevice, &karg.type, &karg.subtype)) | ||
397 | |||
398 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_caps", | ||
399 | me_query_subdevice_caps_t, | ||
400 | me_query_subdevice_caps, | ||
401 | me_device_query_subdevice_caps, | ||
402 | (device, karg.subdevice, &karg.caps)) | ||
403 | |||
404 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_caps_args", | ||
405 | me_query_subdevice_caps_args_t, | ||
406 | me_query_subdevice_caps_args, | ||
407 | me_device_query_subdevice_caps_args, | ||
408 | (device, karg.subdevice, karg.cap, karg.args, | ||
409 | karg.count)) | ||
410 | |||
411 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_ranges", | ||
412 | me_query_number_ranges_t, | ||
413 | me_query_number_ranges, | ||
414 | me_device_query_number_ranges, | ||
415 | (device, karg.subdevice, karg.unit, &karg.number)) | ||
416 | |||
417 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_range_by_min_max", | ||
418 | me_query_range_by_min_max_t, | ||
419 | me_query_range_by_min_max, | ||
420 | me_device_query_range_by_min_max, | ||
421 | (device, | ||
422 | karg.subdevice, | ||
423 | karg.unit, | ||
424 | &karg.min, &karg.max, &karg.max_data, &karg.range)) | ||
425 | |||
426 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_range_info", | ||
427 | me_query_range_info_t, | ||
428 | me_query_range_info, | ||
429 | me_device_query_range_info, | ||
430 | (device, | ||
431 | karg.subdevice, | ||
432 | karg.range, | ||
433 | &karg.unit, &karg.min, &karg.max, &karg.max_data)) | ||
434 | |||
435 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_timer", | ||
436 | me_query_timer_t, | ||
437 | me_query_timer, | ||
438 | me_device_query_timer, | ||
439 | (device, | ||
440 | karg.subdevice, | ||
441 | karg.timer, | ||
442 | &karg.base_frequency, | ||
443 | &karg.min_ticks, &karg.max_ticks)) | ||
444 | |||
445 | ME_QUERY_MULTIPLEX_TEMPLATE("me_query_version_device_driver", | ||
446 | me_query_version_device_driver_t, | ||
447 | me_query_version_device_driver, | ||
448 | me_device_query_version_device_driver, | ||
449 | (device, &karg.version)) | ||
450 | #else | ||
451 | #error macro ME_QUERY_MULTIPLEX_TEMPLATE not defined | ||
452 | #endif | ||
453 | |||
454 | /** ******************************************************************************** **/ | ||
455 | |||
456 | static me_device_t *get_dummy_instance(unsigned short vendor_id, | ||
457 | unsigned short device_id, | ||
458 | unsigned int serial_no, | ||
459 | int bus_type, | ||
460 | int bus_no, int dev_no, int func_no) | ||
461 | { | ||
462 | int err; | ||
463 | me_dummy_constructor_t constructor = NULL; | ||
464 | me_device_t *instance; | ||
465 | |||
466 | PDEBUG("executed.\n"); | ||
467 | |||
468 | if ((constructor = symbol_get(medummy_constructor)) == NULL) { | ||
469 | err = request_module(MEDUMMY_NAME); | ||
470 | |||
471 | if (err) { | ||
472 | PERROR("Error while request for module %s.\n", | ||
473 | MEDUMMY_NAME); | ||
474 | return NULL; | ||
475 | } | ||
476 | |||
477 | if ((constructor = symbol_get(medummy_constructor)) == NULL) { | ||
478 | PERROR("Can't get %s driver module constructor.\n", | ||
479 | MEDUMMY_NAME); | ||
480 | return NULL; | ||
481 | } | ||
482 | } | ||
483 | |||
484 | if ((instance = (*constructor) (vendor_id, | ||
485 | device_id, | ||
486 | serial_no, | ||
487 | bus_type, | ||
488 | bus_no, dev_no, func_no)) == NULL) | ||
489 | symbol_put(medummy_constructor); | ||
490 | |||
491 | return instance; | ||
492 | } | ||
493 | |||
494 | static int __devinit me_probe_pci(struct pci_dev *dev, | ||
495 | const struct pci_device_id *id) | ||
496 | { | ||
497 | int err; | ||
498 | me_pci_constructor_t constructor = NULL; | ||
499 | #ifdef BOSCH | ||
500 | me_bosch_constructor_t constructor_bosch = NULL; | ||
501 | #endif | ||
502 | me_device_t *n_device = NULL; | ||
503 | uint32_t device; | ||
504 | |||
505 | char constructor_name[24] = "me0000_pci_constructor"; | ||
506 | char module_name[7] = "me0000"; | ||
507 | |||
508 | PDEBUG("executed.\n"); | ||
509 | device = dev->device; | ||
510 | if ((device & 0xF000) == 0x6000) { // Exceptions: me61xx, me62xx, me63xx are handled by one driver. | ||
511 | device &= 0xF0FF; | ||
512 | } | ||
513 | |||
514 | constructor_name[2] += (char)((device >> 12) & 0x000F); | ||
515 | constructor_name[3] += (char)((device >> 8) & 0x000F); | ||
516 | PDEBUG("constructor_name: %s\n", constructor_name); | ||
517 | module_name[2] += (char)((device >> 12) & 0x000F); | ||
518 | module_name[3] += (char)((device >> 8) & 0x000F); | ||
519 | PDEBUG("module_name: %s\n", module_name); | ||
520 | |||
521 | if ((constructor = | ||
522 | (me_pci_constructor_t) symbol_get(constructor_name)) == NULL) { | ||
523 | if (request_module("%s", module_name)) { | ||
524 | PERROR("Error while request for module %s.\n", | ||
525 | module_name); | ||
526 | return -ENODEV; | ||
527 | } | ||
528 | |||
529 | if ((constructor = | ||
530 | (me_pci_constructor_t) symbol_get(constructor_name)) == | ||
531 | NULL) { | ||
532 | PERROR("Can't get %s driver module constructor.\n", | ||
533 | module_name); | ||
534 | return -ENODEV; | ||
535 | } | ||
536 | } | ||
537 | #ifdef BOSCH | ||
538 | if ((device & 0xF000) == 0x4000) { // Bosch build has differnt constructor for me4600. | ||
539 | if ((n_device = | ||
540 | (*constructor_bosch) (dev, me_bosch_fw)) == NULL) { | ||
541 | symbol_put(constructor_name); | ||
542 | PERROR | ||
543 | ("Can't get device instance of %s driver module.\n", | ||
544 | module_name); | ||
545 | return -ENODEV; | ||
546 | } | ||
547 | } else { | ||
548 | #endif | ||
549 | if ((n_device = (*constructor) (dev)) == NULL) { | ||
550 | symbol_put(constructor_name); | ||
551 | PERROR | ||
552 | ("Can't get device instance of %s driver module.\n", | ||
553 | module_name); | ||
554 | return -ENODEV; | ||
555 | } | ||
556 | #ifdef BOSCH | ||
557 | } | ||
558 | #endif | ||
559 | |||
560 | insert_to_device_list(n_device); | ||
561 | err = | ||
562 | n_device->me_device_io_reset_device(n_device, NULL, | ||
563 | ME_IO_RESET_DEVICE_NO_FLAGS); | ||
564 | if (err) { | ||
565 | PERROR("Error while reseting device.\n"); | ||
566 | } else { | ||
567 | PDEBUG("Reseting device was sucessful.\n"); | ||
568 | } | ||
569 | return ME_ERRNO_SUCCESS; | ||
570 | } | ||
571 | |||
572 | static void release_instance(me_device_t *device) | ||
573 | { | ||
574 | int vendor_id; | ||
575 | int device_id; | ||
576 | int serial_no; | ||
577 | int bus_type; | ||
578 | int bus_no; | ||
579 | int dev_no; | ||
580 | int func_no; | ||
581 | int plugged; | ||
582 | |||
583 | uint32_t dev_id; | ||
584 | |||
585 | char constructor_name[24] = "me0000_pci_constructor"; | ||
586 | |||
587 | PDEBUG("executed.\n"); | ||
588 | |||
589 | device->me_device_query_info_device(device, | ||
590 | &vendor_id, | ||
591 | &device_id, | ||
592 | &serial_no, | ||
593 | &bus_type, | ||
594 | &bus_no, | ||
595 | &dev_no, &func_no, &plugged); | ||
596 | |||
597 | dev_id = device_id; | ||
598 | device->me_device_destructor(device); | ||
599 | |||
600 | if (plugged != ME_PLUGGED_IN) { | ||
601 | PDEBUG("release: medummy_constructor\n"); | ||
602 | |||
603 | symbol_put("medummy_constructor"); | ||
604 | } else { | ||
605 | if ((dev_id & 0xF000) == 0x6000) { // Exceptions: me61xx, me62xx, me63xx are handled by one driver. | ||
606 | dev_id &= 0xF0FF; | ||
607 | } | ||
608 | |||
609 | constructor_name[2] += (char)((dev_id >> 12) & 0x000F); | ||
610 | constructor_name[3] += (char)((dev_id >> 8) & 0x000F); | ||
611 | PDEBUG("release: %s\n", constructor_name); | ||
612 | |||
613 | symbol_put(constructor_name); | ||
614 | } | ||
615 | } | ||
616 | |||
617 | static int insert_to_device_list(me_device_t *n_device) | ||
618 | { | ||
619 | me_device_t *o_device = NULL; | ||
620 | |||
621 | struct list_head *pos; | ||
622 | int n_vendor_id; | ||
623 | int n_device_id; | ||
624 | int n_serial_no; | ||
625 | int n_bus_type; | ||
626 | int n_bus_no; | ||
627 | int n_dev_no; | ||
628 | int n_func_no; | ||
629 | int n_plugged; | ||
630 | int o_vendor_id; | ||
631 | int o_device_id; | ||
632 | int o_serial_no; | ||
633 | int o_bus_type; | ||
634 | int o_bus_no; | ||
635 | int o_dev_no; | ||
636 | int o_func_no; | ||
637 | int o_plugged; | ||
638 | |||
639 | PDEBUG("executed.\n"); | ||
640 | |||
641 | n_device->me_device_query_info_device(n_device, | ||
642 | &n_vendor_id, | ||
643 | &n_device_id, | ||
644 | &n_serial_no, | ||
645 | &n_bus_type, | ||
646 | &n_bus_no, | ||
647 | &n_dev_no, | ||
648 | &n_func_no, &n_plugged); | ||
649 | |||
650 | down_write(&me_rwsem); | ||
651 | |||
652 | list_for_each(pos, &me_device_list) { | ||
653 | o_device = list_entry(pos, me_device_t, list); | ||
654 | o_device->me_device_query_info_device(o_device, | ||
655 | &o_vendor_id, | ||
656 | &o_device_id, | ||
657 | &o_serial_no, | ||
658 | &o_bus_type, | ||
659 | &o_bus_no, | ||
660 | &o_dev_no, | ||
661 | &o_func_no, &o_plugged); | ||
662 | |||
663 | if (o_plugged == ME_PLUGGED_OUT) { | ||
664 | if (((o_vendor_id == n_vendor_id) && | ||
665 | (o_device_id == n_device_id) && | ||
666 | (o_serial_no == n_serial_no) && | ||
667 | (o_bus_type == n_bus_type)) || | ||
668 | ((o_vendor_id == n_vendor_id) && | ||
669 | (o_device_id == n_device_id) && | ||
670 | (o_bus_type == n_bus_type) && | ||
671 | (o_bus_no == n_bus_no) && | ||
672 | (o_dev_no == n_dev_no) && | ||
673 | (o_func_no == n_func_no))) { | ||
674 | n_device->list.prev = pos->prev; | ||
675 | n_device->list.next = pos->next; | ||
676 | pos->prev->next = &n_device->list; | ||
677 | pos->next->prev = &n_device->list; | ||
678 | release_instance(o_device); | ||
679 | break; | ||
680 | } | ||
681 | } | ||
682 | } | ||
683 | |||
684 | if (pos == &me_device_list) { | ||
685 | list_add_tail(&n_device->list, &me_device_list); | ||
686 | } | ||
687 | |||
688 | up_write(&me_rwsem); | ||
689 | |||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | static void __devexit me_remove_pci(struct pci_dev *dev) | ||
694 | { | ||
695 | int vendor_id = dev->vendor; | ||
696 | int device_id = dev->device; | ||
697 | int subsystem_vendor = dev->subsystem_vendor; | ||
698 | int subsystem_device = dev->subsystem_device; | ||
699 | int serial_no = (subsystem_device << 16) | subsystem_vendor; | ||
700 | |||
701 | PDEBUG("executed.\n"); | ||
702 | |||
703 | PINFO("Vendor id = 0x%08X\n", vendor_id); | ||
704 | PINFO("Device id = 0x%08X\n", device_id); | ||
705 | PINFO("Serial Number = 0x%08X\n", serial_no); | ||
706 | |||
707 | replace_with_dummy(vendor_id, device_id, serial_no); | ||
708 | } | ||
709 | |||
710 | static int replace_with_dummy(int vendor_id, int device_id, int serial_no) | ||
711 | { | ||
712 | |||
713 | struct list_head *pos; | ||
714 | me_device_t *n_device = NULL; | ||
715 | me_device_t *o_device = NULL; | ||
716 | int o_vendor_id; | ||
717 | int o_device_id; | ||
718 | int o_serial_no; | ||
719 | int o_bus_type; | ||
720 | int o_bus_no; | ||
721 | int o_dev_no; | ||
722 | int o_func_no; | ||
723 | int o_plugged; | ||
724 | |||
725 | PDEBUG("executed.\n"); | ||
726 | |||
727 | down_write(&me_rwsem); | ||
728 | |||
729 | list_for_each(pos, &me_device_list) { | ||
730 | o_device = list_entry(pos, me_device_t, list); | ||
731 | o_device->me_device_query_info_device(o_device, | ||
732 | &o_vendor_id, | ||
733 | &o_device_id, | ||
734 | &o_serial_no, | ||
735 | &o_bus_type, | ||
736 | &o_bus_no, | ||
737 | &o_dev_no, | ||
738 | &o_func_no, &o_plugged); | ||
739 | |||
740 | if (o_plugged == ME_PLUGGED_IN) { | ||
741 | if (((o_vendor_id == vendor_id) && | ||
742 | (o_device_id == device_id) && | ||
743 | (o_serial_no == serial_no))) { | ||
744 | n_device = get_dummy_instance(o_vendor_id, | ||
745 | o_device_id, | ||
746 | o_serial_no, | ||
747 | o_bus_type, | ||
748 | o_bus_no, | ||
749 | o_dev_no, | ||
750 | o_func_no); | ||
751 | |||
752 | if (!n_device) { | ||
753 | up_write(&me_rwsem); | ||
754 | PERROR("Cannot get dummy instance.\n"); | ||
755 | return 1; | ||
756 | } | ||
757 | |||
758 | n_device->list.prev = pos->prev; | ||
759 | |||
760 | n_device->list.next = pos->next; | ||
761 | pos->prev->next = &n_device->list; | ||
762 | pos->next->prev = &n_device->list; | ||
763 | release_instance(o_device); | ||
764 | break; | ||
765 | } | ||
766 | } | ||
767 | } | ||
768 | |||
769 | up_write(&me_rwsem); | ||
770 | |||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | static void clear_device_list(void) | ||
775 | { | ||
776 | |||
777 | struct list_head *entry; | ||
778 | me_device_t *device; | ||
779 | |||
780 | // Clear the device info list . | ||
781 | down_write(&me_rwsem); | ||
782 | |||
783 | while (!list_empty(&me_device_list)) { | ||
784 | entry = me_device_list.next; | ||
785 | device = list_entry(entry, me_device_t, list); | ||
786 | list_del(entry); | ||
787 | release_instance(device); | ||
788 | } | ||
789 | |||
790 | up_write(&me_rwsem); | ||
791 | } | ||
792 | |||
793 | static int lock_driver(struct file *filep, int lock, int flags) | ||
794 | { | ||
795 | int err = ME_ERRNO_SUCCESS; | ||
796 | me_device_t *device; | ||
797 | |||
798 | PDEBUG("executed.\n"); | ||
799 | |||
800 | down_read(&me_rwsem); | ||
801 | |||
802 | spin_lock(&me_lock); | ||
803 | |||
804 | switch (lock) { | ||
805 | |||
806 | case ME_LOCK_SET: | ||
807 | if (me_count) { | ||
808 | PERROR | ||
809 | ("Driver System is currently used by another process.\n"); | ||
810 | err = ME_ERRNO_USED; | ||
811 | } else if ((me_filep != NULL) && (me_filep != filep)) { | ||
812 | PERROR | ||
813 | ("Driver System is already logged by another process.\n"); | ||
814 | err = ME_ERRNO_LOCKED; | ||
815 | } else { | ||
816 | list_for_each_entry(device, &me_device_list, list) { | ||
817 | err = | ||
818 | device->me_device_lock_device(device, filep, | ||
819 | ME_LOCK_CHECK, | ||
820 | flags); | ||
821 | |||
822 | if (err) | ||
823 | break; | ||
824 | } | ||
825 | |||
826 | if (!err) | ||
827 | me_filep = filep; | ||
828 | } | ||
829 | |||
830 | break; | ||
831 | |||
832 | case ME_LOCK_RELEASE: | ||
833 | if ((me_filep != NULL) && (me_filep != filep)) { | ||
834 | err = ME_ERRNO_SUCCESS; | ||
835 | } else { | ||
836 | list_for_each_entry(device, &me_device_list, list) { | ||
837 | device->me_device_lock_device(device, filep, | ||
838 | ME_LOCK_RELEASE, | ||
839 | flags); | ||
840 | } | ||
841 | |||
842 | me_filep = NULL; | ||
843 | } | ||
844 | |||
845 | break; | ||
846 | |||
847 | default: | ||
848 | PERROR("Invalid lock specified.\n"); | ||
849 | |||
850 | err = ME_ERRNO_INVALID_LOCK; | ||
851 | |||
852 | break; | ||
853 | } | ||
854 | |||
855 | spin_unlock(&me_lock); | ||
856 | |||
857 | up_read(&me_rwsem); | ||
858 | |||
859 | return err; | ||
860 | } | ||
861 | |||
862 | static int me_lock_driver(struct file *filep, me_lock_driver_t *arg) | ||
863 | { | ||
864 | int err = 0; | ||
865 | |||
866 | me_lock_driver_t lock; | ||
867 | |||
868 | PDEBUG("executed.\n"); | ||
869 | |||
870 | err = copy_from_user(&lock, arg, sizeof(me_lock_driver_t)); | ||
871 | |||
872 | if (err) { | ||
873 | PERROR("Can't copy arguments to kernel space.\n"); | ||
874 | return -EFAULT; | ||
875 | } | ||
876 | |||
877 | lock.errno = lock_driver(filep, lock.lock, lock.flags); | ||
878 | |||
879 | err = copy_to_user(arg, &lock, sizeof(me_lock_driver_t)); | ||
880 | |||
881 | if (err) { | ||
882 | PERROR("Can't copy query back to user space.\n"); | ||
883 | return -EFAULT; | ||
884 | } | ||
885 | |||
886 | return ME_ERRNO_SUCCESS; | ||
887 | } | ||
888 | |||
889 | static int me_open(struct inode *inode_ptr, struct file *filep) | ||
890 | { | ||
891 | |||
892 | PDEBUG("executed.\n"); | ||
893 | // Nothing to do here. | ||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | static int me_release(struct inode *inode_ptr, struct file *filep) | ||
898 | { | ||
899 | |||
900 | PDEBUG("executed.\n"); | ||
901 | lock_driver(filep, ME_LOCK_RELEASE, ME_LOCK_DRIVER_NO_FLAGS); | ||
902 | |||
903 | return 0; | ||
904 | } | ||
905 | |||
906 | static int me_query_version_main_driver(struct file *filep, | ||
907 | me_query_version_main_driver_t *arg) | ||
908 | { | ||
909 | int err; | ||
910 | me_query_version_main_driver_t karg; | ||
911 | |||
912 | PDEBUG("executed.\n"); | ||
913 | |||
914 | karg.version = ME_VERSION_DRIVER; | ||
915 | karg.errno = ME_ERRNO_SUCCESS; | ||
916 | |||
917 | err = copy_to_user(arg, &karg, sizeof(me_query_version_main_driver_t)); | ||
918 | |||
919 | if (err) { | ||
920 | PERROR("Can't copy query back to user space.\n"); | ||
921 | return -EFAULT; | ||
922 | } | ||
923 | |||
924 | return 0; | ||
925 | } | ||
926 | |||
927 | static int me_config_load_device(struct file *filep, | ||
928 | me_cfg_device_entry_t *karg, int device_no) | ||
929 | { | ||
930 | |||
931 | int err = ME_ERRNO_SUCCESS; | ||
932 | int k = 0; | ||
933 | |||
934 | struct list_head *pos = NULL; | ||
935 | me_device_t *device = NULL; | ||
936 | |||
937 | PDEBUG("executed.\n"); | ||
938 | |||
939 | list_for_each(pos, &me_device_list) { | ||
940 | if (k == device_no) { | ||
941 | device = list_entry(pos, me_device_t, list); | ||
942 | break; | ||
943 | } | ||
944 | |||
945 | k++; | ||
946 | } | ||
947 | |||
948 | if (pos == &me_device_list) { | ||
949 | PERROR("Invalid device number specified.\n"); | ||
950 | return ME_ERRNO_INVALID_DEVICE; | ||
951 | } else { | ||
952 | spin_lock(&me_lock); | ||
953 | |||
954 | if ((me_filep != NULL) && (me_filep != filep)) { | ||
955 | spin_unlock(&me_lock); | ||
956 | PERROR("Resource is locked by another process.\n"); | ||
957 | return ME_ERRNO_LOCKED; | ||
958 | } else { | ||
959 | me_count++; | ||
960 | spin_unlock(&me_lock); | ||
961 | |||
962 | err = | ||
963 | device->me_device_config_load(device, filep, karg); | ||
964 | |||
965 | spin_lock(&me_lock); | ||
966 | me_count--; | ||
967 | spin_unlock(&me_lock); | ||
968 | } | ||
969 | } | ||
970 | |||
971 | return err; | ||
972 | } | ||
973 | |||
974 | static int me_config_load(struct file *filep, me_config_load_t *arg) | ||
975 | { | ||
976 | int err; | ||
977 | int i; | ||
978 | me_config_load_t cfg_setup; | ||
979 | me_config_load_t karg_cfg_setup; | ||
980 | |||
981 | struct list_head *pos = NULL; | ||
982 | |||
983 | struct list_head new_list; | ||
984 | me_device_t *o_device; | ||
985 | me_device_t *n_device; | ||
986 | int o_vendor_id; | ||
987 | int o_device_id; | ||
988 | int o_serial_no; | ||
989 | int o_bus_type; | ||
990 | int o_bus_no; | ||
991 | int o_dev_no; | ||
992 | int o_func_no; | ||
993 | int o_plugged; | ||
994 | |||
995 | PDEBUG("executed.\n"); | ||
996 | |||
997 | // Copy argument to kernel space. | ||
998 | err = copy_from_user(&karg_cfg_setup, arg, sizeof(me_config_load_t)); | ||
999 | |||
1000 | if (err) { | ||
1001 | PERROR("Can't copy arguments to kernel space.\n"); | ||
1002 | return -EFAULT; | ||
1003 | } | ||
1004 | // Allocate kernel buffer for device list. | ||
1005 | cfg_setup.device_list = | ||
1006 | kmalloc(sizeof(me_cfg_device_entry_t) * karg_cfg_setup.count, | ||
1007 | GFP_KERNEL); | ||
1008 | |||
1009 | if (!cfg_setup.device_list) { | ||
1010 | PERROR("Can't get buffer %li for device list.\n", | ||
1011 | sizeof(me_cfg_device_entry_t) * karg_cfg_setup.count); | ||
1012 | return -ENOMEM; | ||
1013 | } | ||
1014 | // Copy device list to kernel space. | ||
1015 | err = | ||
1016 | copy_from_user(cfg_setup.device_list, karg_cfg_setup.device_list, | ||
1017 | sizeof(me_cfg_device_entry_t) * | ||
1018 | karg_cfg_setup.count); | ||
1019 | |||
1020 | if (err) { | ||
1021 | PERROR("Can't copy device list to kernel space.\n"); | ||
1022 | kfree(cfg_setup.device_list); | ||
1023 | return -EFAULT; | ||
1024 | } | ||
1025 | |||
1026 | cfg_setup.count = karg_cfg_setup.count; | ||
1027 | |||
1028 | INIT_LIST_HEAD(&new_list); | ||
1029 | |||
1030 | down_write(&me_rwsem); | ||
1031 | |||
1032 | spin_lock(&me_lock); | ||
1033 | |||
1034 | if ((me_filep != NULL) && (me_filep != filep)) { | ||
1035 | spin_unlock(&me_lock); | ||
1036 | PERROR("Driver System is logged by another process.\n"); | ||
1037 | karg_cfg_setup.errno = ME_ERRNO_LOCKED; | ||
1038 | } else { | ||
1039 | me_count++; | ||
1040 | spin_unlock(&me_lock); | ||
1041 | |||
1042 | for (i = 0; i < karg_cfg_setup.count; i++) { | ||
1043 | PDEBUG("me_config_load() device=%d.\n", i); | ||
1044 | if (cfg_setup.device_list[i].tcpip.access_type == | ||
1045 | ME_ACCESS_TYPE_LOCAL) { | ||
1046 | list_for_each(pos, &me_device_list) { | ||
1047 | o_device = | ||
1048 | list_entry(pos, me_device_t, list); | ||
1049 | o_device-> | ||
1050 | me_device_query_info_device | ||
1051 | (o_device, &o_vendor_id, | ||
1052 | &o_device_id, &o_serial_no, | ||
1053 | &o_bus_type, &o_bus_no, &o_dev_no, | ||
1054 | &o_func_no, &o_plugged); | ||
1055 | |||
1056 | if (cfg_setup.device_list[i].info. | ||
1057 | hw_location.bus_type == | ||
1058 | ME_BUS_TYPE_PCI) { | ||
1059 | if (((o_vendor_id == | ||
1060 | cfg_setup.device_list[i]. | ||
1061 | info.vendor_id) | ||
1062 | && (o_device_id == | ||
1063 | cfg_setup. | ||
1064 | device_list[i].info. | ||
1065 | device_id) | ||
1066 | && (o_serial_no == | ||
1067 | cfg_setup. | ||
1068 | device_list[i].info. | ||
1069 | serial_no) | ||
1070 | && (o_bus_type == | ||
1071 | cfg_setup. | ||
1072 | device_list[i].info. | ||
1073 | hw_location.bus_type)) | ||
1074 | || | ||
1075 | ((o_vendor_id == | ||
1076 | cfg_setup.device_list[i]. | ||
1077 | info.vendor_id) | ||
1078 | && (o_device_id == | ||
1079 | cfg_setup. | ||
1080 | device_list[i].info. | ||
1081 | device_id) | ||
1082 | && (o_bus_type == | ||
1083 | cfg_setup. | ||
1084 | device_list[i].info. | ||
1085 | hw_location.bus_type) | ||
1086 | && (o_bus_no == | ||
1087 | cfg_setup. | ||
1088 | device_list[i].info. | ||
1089 | hw_location.pci.bus_no) | ||
1090 | && (o_dev_no == | ||
1091 | cfg_setup. | ||
1092 | device_list[i].info. | ||
1093 | hw_location.pci. | ||
1094 | device_no) | ||
1095 | && (o_func_no == | ||
1096 | cfg_setup. | ||
1097 | device_list[i].info. | ||
1098 | hw_location.pci. | ||
1099 | function_no))) { | ||
1100 | list_move_tail(pos, | ||
1101 | &new_list); | ||
1102 | break; | ||
1103 | } | ||
1104 | } | ||
1105 | /* | ||
1106 | else if (cfg_setup.device_list[i].info.hw_location.bus_type == ME_BUS_TYPE_USB) | ||
1107 | { | ||
1108 | if (((o_vendor_id == cfg_setup.device_list[i].info.vendor_id) && | ||
1109 | (o_device_id == cfg_setup.device_list[i].info.device_id) && | ||
1110 | (o_serial_no == cfg_setup.device_list[i].info.serial_no) && | ||
1111 | (o_bus_type == cfg_setup.device_list[i].info.hw_location.bus_type)) || | ||
1112 | ((o_vendor_id == cfg_setup.device_list[i].info.vendor_id) && | ||
1113 | (o_device_id == cfg_setup.device_list[i].info.device_id) && | ||
1114 | (o_bus_type == cfg_setup.device_list[i].info.hw_location.bus_type) && | ||
1115 | (o_bus_no == cfg_setup.device_list[i].info.hw_location.usb.root_hub_no))) | ||
1116 | { | ||
1117 | list_move_tail(pos, &new_list); | ||
1118 | break; | ||
1119 | } | ||
1120 | } | ||
1121 | */ | ||
1122 | else { | ||
1123 | PERROR("Wrong bus type: %d.\n", | ||
1124 | cfg_setup.device_list[i]. | ||
1125 | info.hw_location. | ||
1126 | bus_type); | ||
1127 | } | ||
1128 | } | ||
1129 | |||
1130 | if (pos == &me_device_list) { // Device is not already in the list | ||
1131 | if (cfg_setup.device_list[i].info. | ||
1132 | hw_location.bus_type == | ||
1133 | ME_BUS_TYPE_PCI) { | ||
1134 | n_device = | ||
1135 | get_dummy_instance | ||
1136 | (cfg_setup.device_list[i]. | ||
1137 | info.vendor_id, | ||
1138 | cfg_setup.device_list[i]. | ||
1139 | info.device_id, | ||
1140 | cfg_setup.device_list[i]. | ||
1141 | info.serial_no, | ||
1142 | cfg_setup.device_list[i]. | ||
1143 | info.hw_location.bus_type, | ||
1144 | cfg_setup.device_list[i]. | ||
1145 | info.hw_location.pci. | ||
1146 | bus_no, | ||
1147 | cfg_setup.device_list[i]. | ||
1148 | info.hw_location.pci. | ||
1149 | device_no, | ||
1150 | cfg_setup.device_list[i]. | ||
1151 | info.hw_location.pci. | ||
1152 | function_no); | ||
1153 | |||
1154 | if (!n_device) { | ||
1155 | PERROR | ||
1156 | ("Can't get dummy instance.\n"); | ||
1157 | kfree(cfg_setup. | ||
1158 | device_list); | ||
1159 | spin_lock(&me_lock); | ||
1160 | me_count--; | ||
1161 | spin_unlock(&me_lock); | ||
1162 | up_write(&me_rwsem); | ||
1163 | return -EFAULT; | ||
1164 | } | ||
1165 | |||
1166 | list_add_tail(&n_device->list, | ||
1167 | &new_list); | ||
1168 | } | ||
1169 | /* | ||
1170 | else if (cfg_setup.device_list[i].info.hw_location.bus_type == ME_BUS_TYPE_USB) | ||
1171 | { | ||
1172 | n_device = get_dummy_instance( | ||
1173 | cfg_setup.device_list[i].info.vendor_id, | ||
1174 | cfg_setup.device_list[i].info.device_id, | ||
1175 | cfg_setup.device_list[i].info.serial_no, | ||
1176 | cfg_setup.device_list[i].info.hw_location.bus_type, | ||
1177 | cfg_setup.device_list[i].info.hw_location.usb.root_hub_no, | ||
1178 | 0, | ||
1179 | 0); | ||
1180 | |||
1181 | if (!n_device) | ||
1182 | { | ||
1183 | PERROR("Can't get dummy instance.\n"); | ||
1184 | kfree(cfg_setup.device_list); | ||
1185 | spin_lock(&me_lock); | ||
1186 | me_count--; | ||
1187 | spin_unlock(&me_lock); | ||
1188 | up_write(&me_rwsem); | ||
1189 | return -EFAULT; | ||
1190 | } | ||
1191 | |||
1192 | list_add_tail(&n_device->list, &new_list); | ||
1193 | } | ||
1194 | */ | ||
1195 | } | ||
1196 | } else { | ||
1197 | n_device = get_dummy_instance(0, | ||
1198 | 0, 0, 0, 0, 0, 0); | ||
1199 | |||
1200 | if (!n_device) { | ||
1201 | PERROR("Can't get dummy instance.\n"); | ||
1202 | kfree(cfg_setup.device_list); | ||
1203 | spin_lock(&me_lock); | ||
1204 | me_count--; | ||
1205 | spin_unlock(&me_lock); | ||
1206 | up_write(&me_rwsem); | ||
1207 | return -EFAULT; | ||
1208 | } | ||
1209 | |||
1210 | list_add_tail(&n_device->list, &new_list); | ||
1211 | } | ||
1212 | } | ||
1213 | |||
1214 | while (!list_empty(&me_device_list)) { | ||
1215 | o_device = | ||
1216 | list_entry(me_device_list.next, me_device_t, list); | ||
1217 | o_device->me_device_query_info_device(o_device, | ||
1218 | &o_vendor_id, | ||
1219 | &o_device_id, | ||
1220 | &o_serial_no, | ||
1221 | &o_bus_type, | ||
1222 | &o_bus_no, | ||
1223 | &o_dev_no, | ||
1224 | &o_func_no, | ||
1225 | &o_plugged); | ||
1226 | |||
1227 | if (o_plugged == ME_PLUGGED_IN) { | ||
1228 | list_move_tail(me_device_list.next, &new_list); | ||
1229 | } else { | ||
1230 | list_del(me_device_list.next); | ||
1231 | release_instance(o_device); | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | // Move temporary new list to global driver list. | ||
1236 | list_splice(&new_list, &me_device_list); | ||
1237 | |||
1238 | karg_cfg_setup.errno = ME_ERRNO_SUCCESS; | ||
1239 | } | ||
1240 | |||
1241 | for (i = 0; i < cfg_setup.count; i++) { | ||
1242 | |||
1243 | karg_cfg_setup.errno = | ||
1244 | me_config_load_device(filep, &cfg_setup.device_list[i], i); | ||
1245 | if (karg_cfg_setup.errno) { | ||
1246 | PERROR("me_config_load_device(%d)=%d\n", i, | ||
1247 | karg_cfg_setup.errno); | ||
1248 | break; | ||
1249 | } | ||
1250 | } | ||
1251 | |||
1252 | spin_lock(&me_lock); | ||
1253 | |||
1254 | me_count--; | ||
1255 | spin_unlock(&me_lock); | ||
1256 | up_write(&me_rwsem); | ||
1257 | |||
1258 | err = copy_to_user(arg, &karg_cfg_setup, sizeof(me_config_load_t)); | ||
1259 | |||
1260 | if (err) { | ||
1261 | PERROR("Can't copy config list to user space.\n"); | ||
1262 | kfree(cfg_setup.device_list); | ||
1263 | return -EFAULT; | ||
1264 | } | ||
1265 | |||
1266 | kfree(cfg_setup.device_list); | ||
1267 | return 0; | ||
1268 | } | ||
1269 | |||
1270 | static int me_io_stream_start(struct file *filep, me_io_stream_start_t *arg) | ||
1271 | { | ||
1272 | int err; | ||
1273 | int i, k; | ||
1274 | |||
1275 | struct list_head *pos; | ||
1276 | me_device_t *device; | ||
1277 | me_io_stream_start_t karg; | ||
1278 | meIOStreamStart_t *list; | ||
1279 | |||
1280 | PDEBUG("executed.\n"); | ||
1281 | |||
1282 | err = copy_from_user(&karg, arg, sizeof(me_io_stream_start_t)); | ||
1283 | |||
1284 | if (err) { | ||
1285 | PERROR("Can't copy arguments to kernel space.\n"); | ||
1286 | return -EFAULT; | ||
1287 | } | ||
1288 | |||
1289 | karg.errno = ME_ERRNO_SUCCESS; | ||
1290 | |||
1291 | list = kmalloc(sizeof(meIOStreamStart_t) * karg.count, GFP_KERNEL); | ||
1292 | |||
1293 | if (!list) { | ||
1294 | PERROR("Can't get buffer for start list.\n"); | ||
1295 | return -ENOMEM; | ||
1296 | } | ||
1297 | |||
1298 | err = | ||
1299 | copy_from_user(list, karg.start_list, | ||
1300 | sizeof(meIOStreamStart_t) * karg.count); | ||
1301 | |||
1302 | if (err) { | ||
1303 | PERROR("Can't copy start list to kernel space.\n"); | ||
1304 | kfree(list); | ||
1305 | return -EFAULT; | ||
1306 | } | ||
1307 | |||
1308 | spin_lock(&me_lock); | ||
1309 | |||
1310 | if ((me_filep != NULL) && (me_filep != filep)) { | ||
1311 | spin_unlock(&me_lock); | ||
1312 | PERROR("Driver System is logged by another process.\n"); | ||
1313 | |||
1314 | for (i = 0; i < karg.count; i++) { | ||
1315 | list[i].iErrno = ME_ERRNO_LOCKED; | ||
1316 | } | ||
1317 | } else { | ||
1318 | me_count++; | ||
1319 | spin_unlock(&me_lock); | ||
1320 | |||
1321 | for (i = 0; i < karg.count; i++) { | ||
1322 | down_read(&me_rwsem); | ||
1323 | k = 0; | ||
1324 | list_for_each(pos, &me_device_list) { | ||
1325 | if (k == list[i].iDevice) { | ||
1326 | device = | ||
1327 | list_entry(pos, me_device_t, list); | ||
1328 | break; | ||
1329 | } | ||
1330 | |||
1331 | k++; | ||
1332 | } | ||
1333 | |||
1334 | if (pos == &me_device_list) { | ||
1335 | up_read(&me_rwsem); | ||
1336 | PERROR("Invalid device number specified.\n"); | ||
1337 | list[i].iErrno = ME_ERRNO_INVALID_DEVICE; | ||
1338 | karg.errno = ME_ERRNO_INVALID_DEVICE; | ||
1339 | break; | ||
1340 | } else { | ||
1341 | list[i].iErrno = | ||
1342 | device->me_device_io_stream_start(device, | ||
1343 | filep, | ||
1344 | list[i]. | ||
1345 | iSubdevice, | ||
1346 | list[i]. | ||
1347 | iStartMode, | ||
1348 | list[i]. | ||
1349 | iTimeOut, | ||
1350 | list[i]. | ||
1351 | iFlags); | ||
1352 | |||
1353 | if (list[i].iErrno) { | ||
1354 | up_read(&me_rwsem); | ||
1355 | karg.errno = list[i].iErrno; | ||
1356 | break; | ||
1357 | } | ||
1358 | } | ||
1359 | |||
1360 | up_read(&me_rwsem); | ||
1361 | } | ||
1362 | |||
1363 | spin_lock(&me_lock); | ||
1364 | |||
1365 | me_count--; | ||
1366 | spin_unlock(&me_lock); | ||
1367 | } | ||
1368 | |||
1369 | err = copy_to_user(arg, &karg, sizeof(me_io_stream_start_t)); | ||
1370 | |||
1371 | if (err) { | ||
1372 | PERROR("Can't copy arguments to user space.\n"); | ||
1373 | kfree(list); | ||
1374 | return -EFAULT; | ||
1375 | } | ||
1376 | |||
1377 | err = | ||
1378 | copy_to_user(karg.start_list, list, | ||
1379 | sizeof(meIOStreamStart_t) * karg.count); | ||
1380 | |||
1381 | if (err) { | ||
1382 | PERROR("Can't copy start list to user space.\n"); | ||
1383 | kfree(list); | ||
1384 | return -EFAULT; | ||
1385 | } | ||
1386 | |||
1387 | kfree(list); | ||
1388 | |||
1389 | return err; | ||
1390 | } | ||
1391 | |||
1392 | static int me_io_single(struct file *filep, me_io_single_t *arg) | ||
1393 | { | ||
1394 | int err; | ||
1395 | int i, k; | ||
1396 | |||
1397 | struct list_head *pos; | ||
1398 | me_device_t *device; | ||
1399 | me_io_single_t karg; | ||
1400 | meIOSingle_t *list; | ||
1401 | |||
1402 | PDEBUG("executed.\n"); | ||
1403 | |||
1404 | err = copy_from_user(&karg, arg, sizeof(me_io_single_t)); | ||
1405 | |||
1406 | if (err) { | ||
1407 | PERROR("Can't copy arguments to kernel space.\n"); | ||
1408 | return -EFAULT; | ||
1409 | } | ||
1410 | |||
1411 | karg.errno = ME_ERRNO_SUCCESS; | ||
1412 | |||
1413 | list = kmalloc(sizeof(meIOSingle_t) * karg.count, GFP_KERNEL); | ||
1414 | |||
1415 | if (!list) { | ||
1416 | PERROR("Can't get buffer for single list.\n"); | ||
1417 | return -ENOMEM; | ||
1418 | } | ||
1419 | |||
1420 | err = | ||
1421 | copy_from_user(list, karg.single_list, | ||
1422 | sizeof(meIOSingle_t) * karg.count); | ||
1423 | |||
1424 | if (err) { | ||
1425 | PERROR("Can't copy single list to kernel space.\n"); | ||
1426 | kfree(list); | ||
1427 | return -EFAULT; | ||
1428 | } | ||
1429 | |||
1430 | spin_lock(&me_lock); | ||
1431 | |||
1432 | if ((me_filep != NULL) && (me_filep != filep)) { | ||
1433 | spin_unlock(&me_lock); | ||
1434 | PERROR("Driver System is logged by another process.\n"); | ||
1435 | |||
1436 | for (i = 0; i < karg.count; i++) { | ||
1437 | list[i].iErrno = ME_ERRNO_LOCKED; | ||
1438 | } | ||
1439 | } else { | ||
1440 | me_count++; | ||
1441 | spin_unlock(&me_lock); | ||
1442 | |||
1443 | for (i = 0; i < karg.count; i++) { | ||
1444 | k = 0; | ||
1445 | |||
1446 | down_read(&me_rwsem); | ||
1447 | |||
1448 | list_for_each(pos, &me_device_list) { | ||
1449 | if (k == list[i].iDevice) { | ||
1450 | device = | ||
1451 | list_entry(pos, me_device_t, list); | ||
1452 | break; | ||
1453 | } | ||
1454 | |||
1455 | k++; | ||
1456 | } | ||
1457 | |||
1458 | if (pos == &me_device_list) { | ||
1459 | up_read(&me_rwsem); | ||
1460 | PERROR("Invalid device number specified.\n"); | ||
1461 | list[i].iErrno = ME_ERRNO_INVALID_DEVICE; | ||
1462 | karg.errno = ME_ERRNO_INVALID_DEVICE; | ||
1463 | break; | ||
1464 | } else { | ||
1465 | if (list[i].iDir == ME_DIR_OUTPUT) { | ||
1466 | list[i].iErrno = | ||
1467 | device-> | ||
1468 | me_device_io_single_write(device, | ||
1469 | filep, | ||
1470 | list[i]. | ||
1471 | iSubdevice, | ||
1472 | list[i]. | ||
1473 | iChannel, | ||
1474 | list[i]. | ||
1475 | iValue, | ||
1476 | list[i]. | ||
1477 | iTimeOut, | ||
1478 | list[i]. | ||
1479 | iFlags); | ||
1480 | |||
1481 | if (list[i].iErrno) { | ||
1482 | up_read(&me_rwsem); | ||
1483 | karg.errno = list[i].iErrno; | ||
1484 | break; | ||
1485 | } | ||
1486 | } else if (list[i].iDir == ME_DIR_INPUT) { | ||
1487 | list[i].iErrno = | ||
1488 | device-> | ||
1489 | me_device_io_single_read(device, | ||
1490 | filep, | ||
1491 | list[i]. | ||
1492 | iSubdevice, | ||
1493 | list[i]. | ||
1494 | iChannel, | ||
1495 | &list[i]. | ||
1496 | iValue, | ||
1497 | list[i]. | ||
1498 | iTimeOut, | ||
1499 | list[i]. | ||
1500 | iFlags); | ||
1501 | |||
1502 | if (list[i].iErrno) { | ||
1503 | up_read(&me_rwsem); | ||
1504 | karg.errno = list[i].iErrno; | ||
1505 | break; | ||
1506 | } | ||
1507 | } else { | ||
1508 | up_read(&me_rwsem); | ||
1509 | PERROR | ||
1510 | ("Invalid single direction specified.\n"); | ||
1511 | list[i].iErrno = ME_ERRNO_INVALID_DIR; | ||
1512 | karg.errno = ME_ERRNO_INVALID_DIR; | ||
1513 | break; | ||
1514 | } | ||
1515 | } | ||
1516 | |||
1517 | up_read(&me_rwsem); | ||
1518 | } | ||
1519 | |||
1520 | spin_lock(&me_lock); | ||
1521 | |||
1522 | me_count--; | ||
1523 | spin_unlock(&me_lock); | ||
1524 | } | ||
1525 | |||
1526 | err = copy_to_user(arg, &karg, sizeof(me_io_single_t)); | ||
1527 | |||
1528 | if (err) { | ||
1529 | PERROR("Can't copy arguments to user space.\n"); | ||
1530 | return -EFAULT; | ||
1531 | } | ||
1532 | |||
1533 | err = | ||
1534 | copy_to_user(karg.single_list, list, | ||
1535 | sizeof(meIOSingle_t) * karg.count); | ||
1536 | |||
1537 | if (err) { | ||
1538 | PERROR("Can't copy single list to user space.\n"); | ||
1539 | kfree(list); | ||
1540 | return -EFAULT; | ||
1541 | } | ||
1542 | |||
1543 | kfree(list); | ||
1544 | |||
1545 | return err; | ||
1546 | } | ||
1547 | |||
1548 | static int me_io_stream_config(struct file *filep, me_io_stream_config_t *arg) | ||
1549 | { | ||
1550 | int err; | ||
1551 | int k = 0; | ||
1552 | |||
1553 | struct list_head *pos; | ||
1554 | me_device_t *device; | ||
1555 | me_io_stream_config_t karg; | ||
1556 | meIOStreamConfig_t *list; | ||
1557 | |||
1558 | PDEBUG("executed.\n"); | ||
1559 | |||
1560 | err = copy_from_user(&karg, arg, sizeof(me_io_stream_config_t)); | ||
1561 | |||
1562 | if (err) { | ||
1563 | PERROR("Can't copy arguments to kernel space.\n"); | ||
1564 | return -EFAULT; | ||
1565 | } | ||
1566 | |||
1567 | list = kmalloc(sizeof(meIOStreamConfig_t) * karg.count, GFP_KERNEL); | ||
1568 | |||
1569 | if (!list) { | ||
1570 | PERROR("Can't get buffer for config list.\n"); | ||
1571 | return -ENOMEM; | ||
1572 | } | ||
1573 | |||
1574 | err = | ||
1575 | copy_from_user(list, karg.config_list, | ||
1576 | sizeof(meIOStreamConfig_t) * karg.count); | ||
1577 | |||
1578 | if (err) { | ||
1579 | PERROR("Can't copy config list to kernel space.\n"); | ||
1580 | kfree(list); | ||
1581 | return -EFAULT; | ||
1582 | } | ||
1583 | |||
1584 | spin_lock(&me_lock); | ||
1585 | |||
1586 | if ((me_filep != NULL) && (me_filep != filep)) { | ||
1587 | spin_unlock(&me_lock); | ||
1588 | PERROR("Driver System is logged by another process.\n"); | ||
1589 | karg.errno = ME_ERRNO_LOCKED; | ||
1590 | } else { | ||
1591 | me_count++; | ||
1592 | spin_unlock(&me_lock); | ||
1593 | |||
1594 | down_read(&me_rwsem); | ||
1595 | |||
1596 | list_for_each(pos, &me_device_list) { | ||
1597 | if (k == karg.device) { | ||
1598 | device = list_entry(pos, me_device_t, list); | ||
1599 | break; | ||
1600 | } | ||
1601 | |||
1602 | k++; | ||
1603 | } | ||
1604 | |||
1605 | if (pos == &me_device_list) { | ||
1606 | PERROR("Invalid device number specified.\n"); | ||
1607 | karg.errno = ME_ERRNO_INVALID_DEVICE; | ||
1608 | } else { | ||
1609 | karg.errno = | ||
1610 | device->me_device_io_stream_config(device, filep, | ||
1611 | karg.subdevice, | ||
1612 | list, karg.count, | ||
1613 | &karg.trigger, | ||
1614 | karg. | ||
1615 | fifo_irq_threshold, | ||
1616 | karg.flags); | ||
1617 | } | ||
1618 | |||
1619 | up_read(&me_rwsem); | ||
1620 | |||
1621 | spin_lock(&me_lock); | ||
1622 | me_count--; | ||
1623 | spin_unlock(&me_lock); | ||
1624 | } | ||
1625 | |||
1626 | err = copy_to_user(arg, &karg, sizeof(me_io_stream_config_t)); | ||
1627 | |||
1628 | if (err) { | ||
1629 | PERROR("Can't copy back to user space.\n"); | ||
1630 | kfree(list); | ||
1631 | return -EFAULT; | ||
1632 | } | ||
1633 | |||
1634 | kfree(list); | ||
1635 | |||
1636 | return err; | ||
1637 | } | ||
1638 | |||
1639 | static int me_query_number_devices(struct file *filep, | ||
1640 | me_query_number_devices_t *arg) | ||
1641 | { | ||
1642 | int err; | ||
1643 | me_query_number_devices_t karg; | ||
1644 | |||
1645 | struct list_head *pos; | ||
1646 | |||
1647 | PDEBUG("executed.\n"); | ||
1648 | |||
1649 | karg.number = 0; | ||
1650 | down_read(&me_rwsem); | ||
1651 | list_for_each(pos, &me_device_list) { | ||
1652 | karg.number++; | ||
1653 | } | ||
1654 | |||
1655 | up_read(&me_rwsem); | ||
1656 | |||
1657 | karg.errno = ME_ERRNO_SUCCESS; | ||
1658 | |||
1659 | err = copy_to_user(arg, &karg, sizeof(me_query_number_devices_t)); | ||
1660 | |||
1661 | if (err) { | ||
1662 | PERROR("Can't copy query back to user space.\n"); | ||
1663 | return -EFAULT; | ||
1664 | } | ||
1665 | |||
1666 | return 0; | ||
1667 | } | ||
1668 | |||
1669 | static int me_io_stream_stop(struct file *filep, me_io_stream_stop_t *arg) | ||
1670 | { | ||
1671 | int err; | ||
1672 | int i, k; | ||
1673 | |||
1674 | struct list_head *pos; | ||
1675 | me_device_t *device; | ||
1676 | me_io_stream_stop_t karg; | ||
1677 | meIOStreamStop_t *list; | ||
1678 | |||
1679 | PDEBUG("executed.\n"); | ||
1680 | |||
1681 | err = copy_from_user(&karg, arg, sizeof(me_io_stream_stop_t)); | ||
1682 | |||
1683 | if (err) { | ||
1684 | PERROR("Can't copy arguments to kernel space.\n"); | ||
1685 | return -EFAULT; | ||
1686 | } | ||
1687 | |||
1688 | karg.errno = ME_ERRNO_SUCCESS; | ||
1689 | |||
1690 | list = kmalloc(sizeof(meIOStreamStop_t) * karg.count, GFP_KERNEL); | ||
1691 | |||
1692 | if (!list) { | ||
1693 | PERROR("Can't get buffer for stop list.\n"); | ||
1694 | return -ENOMEM; | ||
1695 | } | ||
1696 | |||
1697 | err = | ||
1698 | copy_from_user(list, karg.stop_list, | ||
1699 | sizeof(meIOStreamStop_t) * karg.count); | ||
1700 | |||
1701 | if (err) { | ||
1702 | PERROR("Can't copy stop list to kernel space.\n"); | ||
1703 | kfree(list); | ||
1704 | return -EFAULT; | ||
1705 | } | ||
1706 | |||
1707 | spin_lock(&me_lock); | ||
1708 | |||
1709 | if ((me_filep != NULL) && (me_filep != filep)) { | ||
1710 | spin_unlock(&me_lock); | ||
1711 | PERROR("Driver System is logged by another process.\n"); | ||
1712 | |||
1713 | for (i = 0; i < karg.count; i++) { | ||
1714 | list[i].iErrno = ME_ERRNO_LOCKED; | ||
1715 | } | ||
1716 | } else { | ||
1717 | me_count++; | ||
1718 | spin_unlock(&me_lock); | ||
1719 | |||
1720 | for (i = 0; i < karg.count; i++) { | ||
1721 | k = 0; | ||
1722 | down_read(&me_rwsem); | ||
1723 | list_for_each(pos, &me_device_list) { | ||
1724 | if (k == list[i].iDevice) { | ||
1725 | device = | ||
1726 | list_entry(pos, me_device_t, list); | ||
1727 | break; | ||
1728 | } | ||
1729 | |||
1730 | k++; | ||
1731 | } | ||
1732 | |||
1733 | if (pos == &me_device_list) { | ||
1734 | up_read(&me_rwsem); | ||
1735 | PERROR("Invalid device number specified.\n"); | ||
1736 | list[i].iErrno = ME_ERRNO_INVALID_DEVICE; | ||
1737 | karg.errno = ME_ERRNO_INVALID_DEVICE; | ||
1738 | break; | ||
1739 | } else { | ||
1740 | list[i].iErrno = | ||
1741 | device->me_device_io_stream_stop(device, | ||
1742 | filep, | ||
1743 | list[i]. | ||
1744 | iSubdevice, | ||
1745 | list[i]. | ||
1746 | iStopMode, | ||
1747 | list[i]. | ||
1748 | iFlags); | ||
1749 | |||
1750 | if (list[i].iErrno) { | ||
1751 | up_read(&me_rwsem); | ||
1752 | karg.errno = list[i].iErrno; | ||
1753 | break; | ||
1754 | } | ||
1755 | } | ||
1756 | |||
1757 | up_read(&me_rwsem); | ||
1758 | } | ||
1759 | |||
1760 | spin_lock(&me_lock); | ||
1761 | |||
1762 | me_count--; | ||
1763 | spin_unlock(&me_lock); | ||
1764 | } | ||
1765 | |||
1766 | err = copy_to_user(arg, &karg, sizeof(me_io_stream_stop_t)); | ||
1767 | |||
1768 | if (err) { | ||
1769 | PERROR("Can't copy arguments to user space.\n"); | ||
1770 | return -EFAULT; | ||
1771 | } | ||
1772 | |||
1773 | err = | ||
1774 | copy_to_user(karg.stop_list, list, | ||
1775 | sizeof(meIOStreamStop_t) * karg.count); | ||
1776 | |||
1777 | if (err) { | ||
1778 | PERROR("Can't copy stop list to user space.\n"); | ||
1779 | kfree(list); | ||
1780 | return -EFAULT; | ||
1781 | } | ||
1782 | |||
1783 | kfree(list); | ||
1784 | |||
1785 | return err; | ||
1786 | } | ||
1787 | |||
1788 | /* //me_probe_usb | ||
1789 | static int me_probe_usb(struct usb_interface *interface, const struct usb_device_id *id) | ||
1790 | { | ||
1791 | //int err; | ||
1792 | //me_usb_constructor_t *constructor = NULL; | ||
1793 | me_device_t *n_device = NULL; | ||
1794 | |||
1795 | PDEBUG("executed.\n"); | ||
1796 | |||
1797 | switch (id->idProduct) | ||
1798 | { | ||
1799 | case USB_DEVICE_ID_MEPHISTO_S1: | ||
1800 | if((constructor = symbol_get(mephisto_s1_constructor)) == NULL){ | ||
1801 | err = request_module(MEPHISTO_S1_NAME); | ||
1802 | if(err){ | ||
1803 | PERROR("Error while request for module %s.\n", MEPHISTO_S1_NAME); | ||
1804 | return -ENODEV; | ||
1805 | } | ||
1806 | if((constructor = symbol_get(mephisto_s1_constructor)) == NULL){ | ||
1807 | PERROR("Can't get %s driver module constructor.\n", MEPHISTO_S1_NAME); | ||
1808 | return -ENODEV; | ||
1809 | } | ||
1810 | } | ||
1811 | |||
1812 | if((n_device = (*constructor)(interface)) == NULL){ | ||
1813 | symbol_put(mephisto_s1_constructor); | ||
1814 | PERROR("Can't get device instance of %s driver module.\n", MEPHISTO_S1_NAME); | ||
1815 | return -ENODEV; | ||
1816 | } | ||
1817 | |||
1818 | break; | ||
1819 | |||
1820 | default: | ||
1821 | PERROR("Invalid product id.\n"); | ||
1822 | |||
1823 | return -EINVAL; | ||
1824 | } | ||
1825 | |||
1826 | return insert_to_device_list(n_device); | ||
1827 | } | ||
1828 | */ | ||
1829 | |||
1830 | /* //me_disconnect_usb | ||
1831 | static void me_disconnect_usb(struct usb_interface *interface) | ||
1832 | { | ||
1833 | |||
1834 | struct usb_device *device = interface_to_usbdev(interface); | ||
1835 | int vendor_id = device->descriptor.idVendor; | ||
1836 | int device_id = device->descriptor.idProduct; | ||
1837 | int serial_no; | ||
1838 | |||
1839 | sscanf(&device->serial[2], "%x", &serial_no); | ||
1840 | |||
1841 | PDEBUG("executed.\n"); | ||
1842 | |||
1843 | PINFO("Vendor id = 0x%08X\n", vendor_id); | ||
1844 | PINFO("Device id = 0x%08X\n", device_id); | ||
1845 | PINFO("Serial Number = 0x%08X\n", serial_no); | ||
1846 | |||
1847 | replace_with_dummy(vendor_id, device_id, serial_no); | ||
1848 | } | ||
1849 | */ | ||
1850 | |||
1851 | static int me_ioctl(struct inode *inodep, | ||
1852 | struct file *filep, unsigned int service, unsigned long arg) | ||
1853 | { | ||
1854 | |||
1855 | PDEBUG("executed.\n"); | ||
1856 | |||
1857 | if (_IOC_TYPE(service) != MEMAIN_MAGIC) { | ||
1858 | PERROR("Invalid magic number.\n"); | ||
1859 | return -ENOTTY; | ||
1860 | } | ||
1861 | |||
1862 | PDEBUG("service number: 0x%x.\n", service); | ||
1863 | |||
1864 | switch (service) { | ||
1865 | case ME_IO_IRQ_ENABLE: | ||
1866 | return me_io_irq_start(filep, (me_io_irq_start_t *) arg); | ||
1867 | |||
1868 | case ME_IO_IRQ_WAIT: | ||
1869 | return me_io_irq_wait(filep, (me_io_irq_wait_t *) arg); | ||
1870 | |||
1871 | case ME_IO_IRQ_DISABLE: | ||
1872 | return me_io_irq_stop(filep, (me_io_irq_stop_t *) arg); | ||
1873 | |||
1874 | case ME_IO_RESET_DEVICE: | ||
1875 | return me_io_reset_device(filep, (me_io_reset_device_t *) arg); | ||
1876 | |||
1877 | case ME_IO_RESET_SUBDEVICE: | ||
1878 | return me_io_reset_subdevice(filep, | ||
1879 | (me_io_reset_subdevice_t *) arg); | ||
1880 | |||
1881 | case ME_IO_SINGLE_CONFIG: | ||
1882 | return me_io_single_config(filep, | ||
1883 | (me_io_single_config_t *) arg); | ||
1884 | |||
1885 | case ME_IO_SINGLE: | ||
1886 | return me_io_single(filep, (me_io_single_t *) arg); | ||
1887 | |||
1888 | case ME_IO_STREAM_CONFIG: | ||
1889 | return me_io_stream_config(filep, | ||
1890 | (me_io_stream_config_t *) arg); | ||
1891 | |||
1892 | case ME_IO_STREAM_NEW_VALUES: | ||
1893 | return me_io_stream_new_values(filep, | ||
1894 | (me_io_stream_new_values_t *) | ||
1895 | arg); | ||
1896 | |||
1897 | case ME_IO_STREAM_READ: | ||
1898 | return me_io_stream_read(filep, (me_io_stream_read_t *) arg); | ||
1899 | |||
1900 | case ME_IO_STREAM_START: | ||
1901 | return me_io_stream_start(filep, (me_io_stream_start_t *) arg); | ||
1902 | |||
1903 | case ME_IO_STREAM_STATUS: | ||
1904 | return me_io_stream_status(filep, | ||
1905 | (me_io_stream_status_t *) arg); | ||
1906 | |||
1907 | case ME_IO_STREAM_STOP: | ||
1908 | return me_io_stream_stop(filep, (me_io_stream_stop_t *) arg); | ||
1909 | |||
1910 | case ME_IO_STREAM_WRITE: | ||
1911 | return me_io_stream_write(filep, (me_io_stream_write_t *) arg); | ||
1912 | |||
1913 | case ME_LOCK_DRIVER: | ||
1914 | return me_lock_driver(filep, (me_lock_driver_t *) arg); | ||
1915 | |||
1916 | case ME_LOCK_DEVICE: | ||
1917 | return me_lock_device(filep, (me_lock_device_t *) arg); | ||
1918 | |||
1919 | case ME_LOCK_SUBDEVICE: | ||
1920 | return me_lock_subdevice(filep, (me_lock_subdevice_t *) arg); | ||
1921 | |||
1922 | case ME_QUERY_INFO_DEVICE: | ||
1923 | return me_query_info_device(filep, | ||
1924 | (me_query_info_device_t *) arg); | ||
1925 | |||
1926 | case ME_QUERY_DESCRIPTION_DEVICE: | ||
1927 | return me_query_description_device(filep, | ||
1928 | (me_query_description_device_t | ||
1929 | *) arg); | ||
1930 | |||
1931 | case ME_QUERY_NAME_DEVICE: | ||
1932 | return me_query_name_device(filep, | ||
1933 | (me_query_name_device_t *) arg); | ||
1934 | |||
1935 | case ME_QUERY_NAME_DEVICE_DRIVER: | ||
1936 | return me_query_name_device_driver(filep, | ||
1937 | (me_query_name_device_driver_t | ||
1938 | *) arg); | ||
1939 | |||
1940 | case ME_QUERY_NUMBER_DEVICES: | ||
1941 | return me_query_number_devices(filep, | ||
1942 | (me_query_number_devices_t *) | ||
1943 | arg); | ||
1944 | |||
1945 | case ME_QUERY_NUMBER_SUBDEVICES: | ||
1946 | return me_query_number_subdevices(filep, | ||
1947 | (me_query_number_subdevices_t | ||
1948 | *) arg); | ||
1949 | |||
1950 | case ME_QUERY_NUMBER_CHANNELS: | ||
1951 | return me_query_number_channels(filep, | ||
1952 | (me_query_number_channels_t *) | ||
1953 | arg); | ||
1954 | |||
1955 | case ME_QUERY_NUMBER_RANGES: | ||
1956 | return me_query_number_ranges(filep, | ||
1957 | (me_query_number_ranges_t *) arg); | ||
1958 | |||
1959 | case ME_QUERY_RANGE_BY_MIN_MAX: | ||
1960 | return me_query_range_by_min_max(filep, | ||
1961 | (me_query_range_by_min_max_t *) | ||
1962 | arg); | ||
1963 | |||
1964 | case ME_QUERY_RANGE_INFO: | ||
1965 | return me_query_range_info(filep, | ||
1966 | (me_query_range_info_t *) arg); | ||
1967 | |||
1968 | case ME_QUERY_SUBDEVICE_BY_TYPE: | ||
1969 | return me_query_subdevice_by_type(filep, | ||
1970 | (me_query_subdevice_by_type_t | ||
1971 | *) arg); | ||
1972 | |||
1973 | case ME_QUERY_SUBDEVICE_TYPE: | ||
1974 | return me_query_subdevice_type(filep, | ||
1975 | (me_query_subdevice_type_t *) | ||
1976 | arg); | ||
1977 | |||
1978 | case ME_QUERY_SUBDEVICE_CAPS: | ||
1979 | return me_query_subdevice_caps(filep, | ||
1980 | (me_query_subdevice_caps_t *) | ||
1981 | arg); | ||
1982 | |||
1983 | case ME_QUERY_SUBDEVICE_CAPS_ARGS: | ||
1984 | return me_query_subdevice_caps_args(filep, | ||
1985 | (me_query_subdevice_caps_args_t | ||
1986 | *) arg); | ||
1987 | |||
1988 | case ME_QUERY_TIMER: | ||
1989 | return me_query_timer(filep, (me_query_timer_t *) arg); | ||
1990 | |||
1991 | case ME_QUERY_VERSION_MAIN_DRIVER: | ||
1992 | return me_query_version_main_driver(filep, | ||
1993 | (me_query_version_main_driver_t | ||
1994 | *) arg); | ||
1995 | |||
1996 | case ME_QUERY_VERSION_DEVICE_DRIVER: | ||
1997 | return me_query_version_device_driver(filep, | ||
1998 | (me_query_version_device_driver_t | ||
1999 | *) arg); | ||
2000 | |||
2001 | case ME_CONFIG_LOAD: | ||
2002 | return me_config_load(filep, (me_config_load_t *) arg); | ||
2003 | } | ||
2004 | |||
2005 | PERROR("Invalid ioctl number.\n"); | ||
2006 | return -ENOTTY; | ||
2007 | } | ||
2008 | |||
2009 | static struct miscdevice me_miscdev = { | ||
2010 | .minor = MISC_DYNAMIC_MINOR, | ||
2011 | .name = MEMAIN_NAME, | ||
2012 | .fops = &me_file_operations, | ||
2013 | }; | ||
2014 | |||
2015 | // Init and exit of module. | ||
2016 | static int memain_init(void) | ||
2017 | { | ||
2018 | int result = 0; | ||
2019 | |||
2020 | PDEBUG("executed.\n"); | ||
2021 | |||
2022 | // Register pci driver. This will return 0 if the PCI subsystem is not available. | ||
2023 | result = pci_register_driver(&me_pci_driver); | ||
2024 | |||
2025 | if (result < 0) { | ||
2026 | PERROR("Can't register pci driver.\n"); | ||
2027 | goto INIT_ERROR_1; | ||
2028 | } | ||
2029 | |||
2030 | /* | ||
2031 | // Register usb driver. This will return -ENODEV if no USB subsystem is available. | ||
2032 | result = usb_register(&me_usb_driver); | ||
2033 | |||
2034 | if (result) | ||
2035 | { | ||
2036 | if (result == -ENODEV) | ||
2037 | { | ||
2038 | PERROR("No USB subsystem available.\n"); | ||
2039 | } | ||
2040 | else | ||
2041 | { | ||
2042 | PERROR("Can't register usb driver.\n"); | ||
2043 | goto INIT_ERROR_2; | ||
2044 | } | ||
2045 | } | ||
2046 | */ | ||
2047 | result = misc_register(&me_miscdev); | ||
2048 | if (result < 0) { | ||
2049 | printk(KERN_ERR MEMAIN_NAME ": can't register misc device\n"); | ||
2050 | goto INIT_ERROR_3; | ||
2051 | } | ||
2052 | |||
2053 | return 0; | ||
2054 | |||
2055 | INIT_ERROR_3: | ||
2056 | // usb_deregister(&me_usb_driver); | ||
2057 | |||
2058 | //INIT_ERROR_2: | ||
2059 | pci_unregister_driver(&me_pci_driver); | ||
2060 | clear_device_list(); | ||
2061 | |||
2062 | INIT_ERROR_1: | ||
2063 | return result; | ||
2064 | } | ||
2065 | |||
2066 | static void __exit memain_exit(void) | ||
2067 | { | ||
2068 | PDEBUG("executed.\n"); | ||
2069 | |||
2070 | misc_deregister(&me_miscdev); | ||
2071 | pci_unregister_driver(&me_pci_driver); | ||
2072 | // usb_deregister(&me_usb_driver); | ||
2073 | clear_device_list(); | ||
2074 | } | ||
2075 | |||
2076 | module_init(memain_init); | ||
2077 | module_exit(memain_exit); | ||
2078 | |||
2079 | // Administrative stuff for modinfo. | ||
2080 | MODULE_AUTHOR | ||
2081 | ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>"); | ||
2082 | MODULE_DESCRIPTION("Central module for Meilhaus Driver System."); | ||
2083 | MODULE_SUPPORTED_DEVICE("Meilhaus PCI/cPCI boards."); | ||
2084 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/memain.h b/drivers/staging/meilhaus/memain.h deleted file mode 100644 index 48f83679379e..000000000000 --- a/drivers/staging/meilhaus/memain.h +++ /dev/null | |||
@@ -1,266 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : memain.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | */ | ||
7 | |||
8 | #ifndef _MEMAIN_H_ | ||
9 | #define _MEMAIN_H_ | ||
10 | |||
11 | #include "meinternal.h" | ||
12 | |||
13 | #include "meids.h" | ||
14 | #include "medebug.h" | ||
15 | |||
16 | #include "medevice.h" | ||
17 | /*#include "me1000_device.h" | ||
18 | #include "me1400_device.h" | ||
19 | #include "me1600_device.h"*/ | ||
20 | #include "me4600_device.h" | ||
21 | /*#include "me6000_device.h" | ||
22 | #include "me0600_device.h" | ||
23 | #include "me8100_device.h" | ||
24 | #include "me8200_device.h" | ||
25 | #include "me0900_device.h"*/ | ||
26 | #include "medummy.h" | ||
27 | |||
28 | #ifdef __KERNEL__ | ||
29 | |||
30 | /*============================================================================= | ||
31 | Templates | ||
32 | ===========================================================================*/ | ||
33 | |||
34 | #define ME_LOCK_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ | ||
35 | static int CALL(struct file *filep, TYPE *arg){ \ | ||
36 | int err = 0; \ | ||
37 | int k = 0; \ | ||
38 | struct list_head *pos; \ | ||
39 | me_device_t *device; \ | ||
40 | TYPE karg; \ | ||
41 | \ | ||
42 | PDEBUG("executed.\n"); \ | ||
43 | \ | ||
44 | err = copy_from_user(&karg, arg, sizeof(TYPE)); \ | ||
45 | if(err){ \ | ||
46 | PERROR("Can't copy arguments to kernel space\n"); \ | ||
47 | return -EFAULT; \ | ||
48 | } \ | ||
49 | \ | ||
50 | down_read(&me_rwsem); \ | ||
51 | \ | ||
52 | list_for_each(pos, &me_device_list){ \ | ||
53 | if(k == karg.device){ \ | ||
54 | device = list_entry(pos, me_device_t, list); \ | ||
55 | break; \ | ||
56 | } \ | ||
57 | k++; \ | ||
58 | } \ | ||
59 | \ | ||
60 | if(pos == &me_device_list){ \ | ||
61 | PERROR("Invalid device number specified\n"); \ | ||
62 | karg.errno = ME_ERRNO_INVALID_DEVICE; \ | ||
63 | } \ | ||
64 | else{ \ | ||
65 | spin_lock(&me_lock); \ | ||
66 | if((me_filep != NULL) && (me_filep != filep)){ \ | ||
67 | spin_unlock(&me_lock); \ | ||
68 | PERROR("Resource is locked by another process\n"); \ | ||
69 | if(karg.lock == ME_LOCK_SET) \ | ||
70 | karg.errno = ME_ERRNO_LOCKED; \ | ||
71 | else if(karg.lock == ME_LOCK_RELEASE) \ | ||
72 | karg.errno = ME_ERRNO_SUCCESS; \ | ||
73 | else{ \ | ||
74 | PERROR("Invalid lock specified\n"); \ | ||
75 | karg.errno = ME_ERRNO_INVALID_LOCK; \ | ||
76 | }\ | ||
77 | } \ | ||
78 | else { \ | ||
79 | me_count++; \ | ||
80 | spin_unlock(&me_lock); \ | ||
81 | \ | ||
82 | karg.errno = device->DEV_CALL ARGS; \ | ||
83 | \ | ||
84 | spin_lock(&me_lock); \ | ||
85 | me_count--; \ | ||
86 | spin_unlock(&me_lock); \ | ||
87 | } \ | ||
88 | } \ | ||
89 | \ | ||
90 | up_read(&me_rwsem); \ | ||
91 | \ | ||
92 | err = copy_to_user(arg, &karg, sizeof(TYPE)); \ | ||
93 | if(err){ \ | ||
94 | PERROR("Can't copy arguments back to user space\n"); \ | ||
95 | return -EFAULT; \ | ||
96 | } \ | ||
97 | \ | ||
98 | return ME_ERRNO_SUCCESS; \ | ||
99 | } | ||
100 | |||
101 | #define ME_IO_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ | ||
102 | static int CALL(struct file *filep, TYPE *arg){ \ | ||
103 | int err = 0; \ | ||
104 | int k = 0; \ | ||
105 | struct list_head *pos; \ | ||
106 | me_device_t *device; \ | ||
107 | TYPE karg; \ | ||
108 | \ | ||
109 | PDEBUG("executed.\n"); \ | ||
110 | \ | ||
111 | err = copy_from_user(&karg, arg, sizeof(TYPE)); \ | ||
112 | if(err){ \ | ||
113 | PERROR("Can't copy arguments to kernel space\n"); \ | ||
114 | return -EFAULT; \ | ||
115 | } \ | ||
116 | \ | ||
117 | down_read(&me_rwsem); \ | ||
118 | \ | ||
119 | list_for_each(pos, &me_device_list){ \ | ||
120 | if(k == karg.device){ \ | ||
121 | device = list_entry(pos, me_device_t, list); \ | ||
122 | break; \ | ||
123 | } \ | ||
124 | k++; \ | ||
125 | } \ | ||
126 | \ | ||
127 | if(pos == &me_device_list){ \ | ||
128 | PERROR("Invalid device number specified\n"); \ | ||
129 | karg.errno = ME_ERRNO_INVALID_DEVICE; \ | ||
130 | } \ | ||
131 | else{ \ | ||
132 | spin_lock(&me_lock); \ | ||
133 | if((me_filep != NULL) && (me_filep != filep)){ \ | ||
134 | spin_unlock(&me_lock); \ | ||
135 | PERROR("Resource is locked by another process\n"); \ | ||
136 | karg.errno = ME_ERRNO_LOCKED; \ | ||
137 | } \ | ||
138 | else { \ | ||
139 | me_count++; \ | ||
140 | spin_unlock(&me_lock); \ | ||
141 | \ | ||
142 | karg.errno = device->DEV_CALL ARGS; \ | ||
143 | \ | ||
144 | spin_lock(&me_lock); \ | ||
145 | me_count--; \ | ||
146 | spin_unlock(&me_lock); \ | ||
147 | } \ | ||
148 | } \ | ||
149 | \ | ||
150 | up_read(&me_rwsem); \ | ||
151 | \ | ||
152 | err = copy_to_user(arg, &karg, sizeof(TYPE)); \ | ||
153 | if(err){ \ | ||
154 | PERROR("Can't copy arguments back to user space\n"); \ | ||
155 | return -EFAULT; \ | ||
156 | } \ | ||
157 | \ | ||
158 | return ME_ERRNO_SUCCESS; \ | ||
159 | } | ||
160 | |||
161 | #define ME_QUERY_MULTIPLEX_STR_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ | ||
162 | static int CALL(struct file *filep, TYPE *arg){ \ | ||
163 | int err = 0; \ | ||
164 | int k = 0; \ | ||
165 | struct list_head *pos; \ | ||
166 | me_device_t *device; \ | ||
167 | char *msg = NULL; \ | ||
168 | TYPE karg; \ | ||
169 | \ | ||
170 | PDEBUG("executed.\n"); \ | ||
171 | \ | ||
172 | err = copy_from_user(&karg, arg, sizeof(TYPE)); \ | ||
173 | if(err){ \ | ||
174 | PERROR("Can't copy arguments to kernel space\n"); \ | ||
175 | return -EFAULT; \ | ||
176 | } \ | ||
177 | \ | ||
178 | down_read(&me_rwsem); \ | ||
179 | \ | ||
180 | list_for_each(pos, &me_device_list){ \ | ||
181 | if(k == karg.device){ \ | ||
182 | device = list_entry(pos, me_device_t, list); \ | ||
183 | break; \ | ||
184 | } \ | ||
185 | k++; \ | ||
186 | } \ | ||
187 | \ | ||
188 | if(pos == &me_device_list){ \ | ||
189 | PERROR("Invalid device number specified\n"); \ | ||
190 | karg.errno = ME_ERRNO_INVALID_DEVICE; \ | ||
191 | } \ | ||
192 | else{ \ | ||
193 | karg.errno = device->DEV_CALL ARGS; \ | ||
194 | if(!karg.errno){ \ | ||
195 | if((strlen(msg) + 1) > karg.count){ \ | ||
196 | PERROR("User buffer for device name is to little\n"); \ | ||
197 | karg.errno = ME_ERRNO_USER_BUFFER_SIZE; \ | ||
198 | } \ | ||
199 | else{ \ | ||
200 | err = copy_to_user(karg.name, msg, strlen(msg) + 1); \ | ||
201 | if(err){ \ | ||
202 | PERROR("Can't copy device name to user space\n"); \ | ||
203 | return -EFAULT; \ | ||
204 | } \ | ||
205 | } \ | ||
206 | } \ | ||
207 | } \ | ||
208 | \ | ||
209 | up_read(&me_rwsem); \ | ||
210 | \ | ||
211 | err = copy_to_user(arg, &karg, sizeof(TYPE)); \ | ||
212 | if(err){ \ | ||
213 | PERROR("Can't copy query back to user space\n"); \ | ||
214 | return -EFAULT; \ | ||
215 | } \ | ||
216 | \ | ||
217 | return ME_ERRNO_SUCCESS; \ | ||
218 | } | ||
219 | |||
220 | #define ME_QUERY_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ | ||
221 | static int CALL(struct file *filep, TYPE *arg){ \ | ||
222 | int err = 0; \ | ||
223 | int k = 0; \ | ||
224 | struct list_head *pos; \ | ||
225 | me_device_t *device; \ | ||
226 | TYPE karg; \ | ||
227 | \ | ||
228 | PDEBUG("executed.\n"); \ | ||
229 | \ | ||
230 | err = copy_from_user(&karg, arg, sizeof(TYPE)); \ | ||
231 | if(err){ \ | ||
232 | PERROR("Can't copy arguments from user space\n"); \ | ||
233 | return -EFAULT; \ | ||
234 | } \ | ||
235 | \ | ||
236 | down_read(&me_rwsem); \ | ||
237 | \ | ||
238 | list_for_each(pos, &me_device_list){ \ | ||
239 | if(k == karg.device){ \ | ||
240 | device = list_entry(pos, me_device_t, list); \ | ||
241 | break; \ | ||
242 | } \ | ||
243 | k++; \ | ||
244 | } \ | ||
245 | \ | ||
246 | if(pos == &me_device_list){ \ | ||
247 | PERROR("Invalid device number specified\n"); \ | ||
248 | karg.errno = ME_ERRNO_INVALID_DEVICE; \ | ||
249 | } \ | ||
250 | else{ \ | ||
251 | karg.errno = device->DEV_CALL ARGS; \ | ||
252 | } \ | ||
253 | \ | ||
254 | up_read(&me_rwsem); \ | ||
255 | \ | ||
256 | err = copy_to_user(arg, &karg, sizeof(TYPE)); \ | ||
257 | if(err){ \ | ||
258 | PERROR("Can't copy arguments to user space\n"); \ | ||
259 | return -EFAULT; \ | ||
260 | } \ | ||
261 | \ | ||
262 | return ME_ERRNO_SUCCESS; \ | ||
263 | } | ||
264 | |||
265 | #endif //__KERNEL__ | ||
266 | #endif | ||
diff --git a/drivers/staging/meilhaus/meplx_reg.h b/drivers/staging/meilhaus/meplx_reg.h deleted file mode 100644 index 1868614dc232..000000000000 --- a/drivers/staging/meilhaus/meplx_reg.h +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /** | ||
2 | * @file meplx_reg.h | ||
3 | * | ||
4 | * @brief PLX 9052 PCI bridge register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _MEPLX_REG_H_ | ||
28 | #define _MEPLX_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define PLX_INTCSR 0x4C /**< Interrupt control and status register. */ | ||
33 | #define PLX_INTCSR_LOCAL_INT1_EN 0x01 /**< If set, local interrupt 1 is enabled (r/w). */ | ||
34 | #define PLX_INTCSR_LOCAL_INT1_POL 0x02 /**< If set, local interrupt 1 polarity is active high (r/w). */ | ||
35 | #define PLX_INTCSR_LOCAL_INT1_STATE 0x04 /**< If set, local interrupt 1 is active (r/_). */ | ||
36 | #define PLX_INTCSR_LOCAL_INT2_EN 0x08 /**< If set, local interrupt 2 is enabled (r/w). */ | ||
37 | #define PLX_INTCSR_LOCAL_INT2_POL 0x10 /**< If set, local interrupt 2 polarity is active high (r/w). */ | ||
38 | #define PLX_INTCSR_LOCAL_INT2_STATE 0x20 /**< If set, local interrupt 2 is active (r/_). */ | ||
39 | #define PLX_INTCSR_PCI_INT_EN 0x40 /**< If set, PCI interrupt is enabled (r/w). */ | ||
40 | #define PLX_INTCSR_SOFT_INT 0x80 /**< If set, a software interrupt is generated (r/w). */ | ||
41 | |||
42 | #define PLX_ICR 0x50 /**< Initialization control register. */ | ||
43 | #define PLX_ICR_BIT_EEPROM_CLOCK_SET 0x01000000 | ||
44 | #define PLX_ICR_BIT_EEPROM_CHIP_SELECT 0x02000000 | ||
45 | #define PLX_ICR_BIT_EEPROM_WRITE 0x04000000 | ||
46 | #define PLX_ICR_BIT_EEPROM_READ 0x08000000 | ||
47 | #define PLX_ICR_BIT_EEPROM_VALID 0x10000000 | ||
48 | |||
49 | #define PLX_ICR_MASK_EEPROM 0x1F000000 | ||
50 | #define EEPROM_DELAY 1 | ||
51 | |||
52 | #endif | ||
53 | #endif | ||
diff --git a/drivers/staging/meilhaus/meslist.c b/drivers/staging/meilhaus/meslist.c deleted file mode 100644 index ce49114df55f..000000000000 --- a/drivers/staging/meilhaus/meslist.c +++ /dev/null | |||
@@ -1,173 +0,0 @@ | |||
1 | /** | ||
2 | * @file me_slist.c | ||
3 | * | ||
4 | * @brief Implements the subdevice list class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include "meerror.h" | ||
28 | #include "medefines.h" | ||
29 | |||
30 | #include "meslist.h" | ||
31 | #include "medebug.h" | ||
32 | |||
33 | int me_slist_query_number_subdevices(struct me_slist *slist, int *number) | ||
34 | { | ||
35 | PDEBUG_LOCKS("called.\n"); | ||
36 | *number = slist->n; | ||
37 | return ME_ERRNO_SUCCESS; | ||
38 | } | ||
39 | |||
40 | unsigned int me_slist_get_number_subdevices(struct me_slist *slist) | ||
41 | { | ||
42 | PDEBUG_LOCKS("called.\n"); | ||
43 | return slist->n; | ||
44 | } | ||
45 | |||
46 | me_subdevice_t *me_slist_get_subdevice(struct me_slist * slist, | ||
47 | unsigned int index) | ||
48 | { | ||
49 | |||
50 | struct list_head *pos; | ||
51 | me_subdevice_t *subdevice = NULL; | ||
52 | unsigned int i = 0; | ||
53 | |||
54 | PDEBUG_LOCKS("called.\n"); | ||
55 | |||
56 | if (index >= slist->n) { | ||
57 | PERROR("Index out of range.\n"); | ||
58 | return NULL; | ||
59 | } | ||
60 | |||
61 | list_for_each(pos, &slist->head) { | ||
62 | if (i == index) { | ||
63 | subdevice = list_entry(pos, me_subdevice_t, list); | ||
64 | break; | ||
65 | } | ||
66 | |||
67 | ++i; | ||
68 | } | ||
69 | |||
70 | return subdevice; | ||
71 | } | ||
72 | |||
73 | int me_slist_get_subdevice_by_type(struct me_slist *slist, | ||
74 | unsigned int start_subdevice, | ||
75 | int type, int subtype, int *subdevice) | ||
76 | { | ||
77 | me_subdevice_t *pos; | ||
78 | int s_type, s_subtype; | ||
79 | unsigned int index = 0; | ||
80 | |||
81 | PDEBUG_LOCKS("called.\n"); | ||
82 | |||
83 | if (start_subdevice >= slist->n) { | ||
84 | PERROR("Start index out of range.\n"); | ||
85 | return ME_ERRNO_NOMORE_SUBDEVICE_TYPE; | ||
86 | } | ||
87 | |||
88 | list_for_each_entry(pos, &slist->head, list) { | ||
89 | if (index < start_subdevice) { // Go forward to start subdevice. | ||
90 | ++index; | ||
91 | continue; | ||
92 | } | ||
93 | |||
94 | pos->me_subdevice_query_subdevice_type(pos, | ||
95 | &s_type, &s_subtype); | ||
96 | |||
97 | if (subtype == ME_SUBTYPE_ANY) { | ||
98 | if (s_type == type) | ||
99 | break; | ||
100 | } else { | ||
101 | if ((s_type == type) && (s_subtype == subtype)) | ||
102 | break; | ||
103 | } | ||
104 | |||
105 | ++index; | ||
106 | } | ||
107 | |||
108 | if (index >= slist->n) { | ||
109 | return ME_ERRNO_NOMORE_SUBDEVICE_TYPE; | ||
110 | } | ||
111 | |||
112 | *subdevice = index; | ||
113 | |||
114 | return ME_ERRNO_SUCCESS; | ||
115 | } | ||
116 | |||
117 | void me_slist_add_subdevice_tail(struct me_slist *slist, | ||
118 | me_subdevice_t *subdevice) | ||
119 | { | ||
120 | PDEBUG_LOCKS("called.\n"); | ||
121 | |||
122 | list_add_tail(&subdevice->list, &slist->head); | ||
123 | ++slist->n; | ||
124 | } | ||
125 | |||
126 | me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist) | ||
127 | { | ||
128 | |||
129 | struct list_head *last; | ||
130 | me_subdevice_t *subdevice; | ||
131 | |||
132 | PDEBUG_LOCKS("called.\n"); | ||
133 | |||
134 | if (list_empty(&slist->head)) | ||
135 | return NULL; | ||
136 | |||
137 | last = slist->head.prev; | ||
138 | |||
139 | subdevice = list_entry(last, me_subdevice_t, list); | ||
140 | |||
141 | list_del(last); | ||
142 | |||
143 | --slist->n; | ||
144 | |||
145 | return subdevice; | ||
146 | } | ||
147 | |||
148 | int me_slist_init(me_slist_t *slist) | ||
149 | { | ||
150 | PDEBUG_LOCKS("called.\n"); | ||
151 | |||
152 | INIT_LIST_HEAD(&slist->head); | ||
153 | slist->n = 0; | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | void me_slist_deinit(me_slist_t *slist) | ||
158 | { | ||
159 | |||
160 | struct list_head *s; | ||
161 | me_subdevice_t *subdevice; | ||
162 | |||
163 | PDEBUG_LOCKS("called.\n"); | ||
164 | |||
165 | while (!list_empty(&slist->head)) { | ||
166 | s = slist->head.next; | ||
167 | list_del(s); | ||
168 | subdevice = list_entry(s, me_subdevice_t, list); | ||
169 | subdevice->me_subdevice_destructor(subdevice); | ||
170 | } | ||
171 | |||
172 | slist->n = 0; | ||
173 | } | ||
diff --git a/drivers/staging/meilhaus/meslist.h b/drivers/staging/meilhaus/meslist.h deleted file mode 100644 index d26c89693d2c..000000000000 --- a/drivers/staging/meilhaus/meslist.h +++ /dev/null | |||
@@ -1,108 +0,0 @@ | |||
1 | /** | ||
2 | * @file me_slist.h | ||
3 | * | ||
4 | * @brief Provides the subdevice list class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _ME_SLIST_H_ | ||
10 | #define _ME_SLIST_H_ | ||
11 | |||
12 | #include <linux/list.h> | ||
13 | |||
14 | #include "mesubdevice.h" | ||
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | |||
18 | /** | ||
19 | * @brief The subdevice list container. | ||
20 | */ | ||
21 | typedef struct me_slist { | ||
22 | struct list_head head; /**< The head of the internal list. */ | ||
23 | unsigned int n; /**< The number of subdevices in the list. */ | ||
24 | } me_slist_t; | ||
25 | |||
26 | /** | ||
27 | * @brief Queries the number of subdevices currently inside the list. | ||
28 | * | ||
29 | * @param slist The subdevice list to query. | ||
30 | * @param[out] number The number of subdevices of the device. | ||
31 | * | ||
32 | * @return ME-iDS error code. | ||
33 | */ | ||
34 | int me_slist_query_number_subdevices(struct me_slist *slist, int *number); | ||
35 | |||
36 | /** | ||
37 | * @brief Returns the number of subdevices currently inside the list. | ||
38 | * | ||
39 | * @param slist The subdevice list to query. | ||
40 | * | ||
41 | * @return The number of subdevices in the list. | ||
42 | */ | ||
43 | unsigned int me_slist_get_number_subdevices(struct me_slist *slist); | ||
44 | |||
45 | /** | ||
46 | * @brief Get a subdevice by index. | ||
47 | * | ||
48 | * @param slist The subdevice list to query. | ||
49 | * @param index The index of the subdevice to get in the list. | ||
50 | * | ||
51 | * @return The subdevice at index if available.\n | ||
52 | * NULL if the index is out of range. | ||
53 | */ | ||
54 | me_subdevice_t *me_slist_get_subdevice(struct me_slist *slist, | ||
55 | unsigned int index); | ||
56 | |||
57 | /** | ||
58 | * @brief Get a subdevice index by type and subtype. | ||
59 | * | ||
60 | * @param slist The subdevice list to query. | ||
61 | * @param start_subdevice The subdevice index at which the start shall begin. | ||
62 | * @param type The type of the subdevice to query. | ||
63 | * @param subtype The subtype of the subdevice to query. | ||
64 | * @param[out] subdevice On success this parameter returns the index of the subdevice matching the requested type. | ||
65 | * | ||
66 | * @return ME_ERRNO_SUCCESS on success. | ||
67 | */ | ||
68 | int me_slist_get_subdevice_by_type(struct me_slist *slist, | ||
69 | unsigned int start_subdevice, | ||
70 | int type, int subtype, int *subdevice); | ||
71 | |||
72 | /** | ||
73 | * @brief Adds a subdevice to the tail of the list. | ||
74 | * | ||
75 | * @param slist The subdevice list to add a subdevice to. | ||
76 | * @param subdevice The subdevice to add to the list. | ||
77 | */ | ||
78 | void me_slist_add_subdevice_tail(struct me_slist *slist, | ||
79 | me_subdevice_t * subdevice); | ||
80 | |||
81 | /** | ||
82 | * @brief Removes a subdevice from the tail of the list. | ||
83 | * | ||
84 | * @param slist The subdevice list. | ||
85 | * | ||
86 | * @return Pointer to the removed subdeivce.\n | ||
87 | * NULL in cases where the list was empty. | ||
88 | */ | ||
89 | me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist); | ||
90 | |||
91 | /** | ||
92 | * @brief Initializes a subdevice list structure. | ||
93 | * | ||
94 | * @param lock The subdevice list structure to initialize. | ||
95 | * @return 0 on success. | ||
96 | */ | ||
97 | int me_slist_init(me_slist_t * slist); | ||
98 | |||
99 | /** | ||
100 | * @brief Deinitializes a subdevice list structure and destructs every subdevice in it. | ||
101 | * | ||
102 | * @param slist The subdevice list structure to deinitialize. | ||
103 | * @return 0 on success. | ||
104 | */ | ||
105 | void me_slist_deinit(me_slist_t * slist); | ||
106 | |||
107 | #endif | ||
108 | #endif | ||
diff --git a/drivers/staging/meilhaus/meslock.c b/drivers/staging/meilhaus/meslock.c deleted file mode 100644 index abcdb4a2eba6..000000000000 --- a/drivers/staging/meilhaus/meslock.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /** | ||
2 | * @file meslock.c | ||
3 | * | ||
4 | * @brief Implements the subdevice lock class. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #include <linux/spinlock.h> | ||
28 | |||
29 | #include "medefines.h" | ||
30 | #include "meerror.h" | ||
31 | |||
32 | #include "medebug.h" | ||
33 | #include "meslock.h" | ||
34 | |||
35 | int me_slock_enter(struct me_slock *slock, struct file *filep) | ||
36 | { | ||
37 | PDEBUG_LOCKS("executed.\n"); | ||
38 | |||
39 | spin_lock(&slock->spin_lock); | ||
40 | |||
41 | if ((slock->filep) != NULL && (slock->filep != filep)) { | ||
42 | PERROR("Subdevice is locked by another process.\n"); | ||
43 | spin_unlock(&slock->spin_lock); | ||
44 | return ME_ERRNO_LOCKED; | ||
45 | } | ||
46 | |||
47 | slock->count++; | ||
48 | |||
49 | spin_unlock(&slock->spin_lock); | ||
50 | |||
51 | return ME_ERRNO_SUCCESS; | ||
52 | } | ||
53 | |||
54 | int me_slock_exit(struct me_slock *slock, struct file *filep) | ||
55 | { | ||
56 | PDEBUG_LOCKS("executed.\n"); | ||
57 | |||
58 | spin_lock(&slock->spin_lock); | ||
59 | slock->count--; | ||
60 | spin_unlock(&slock->spin_lock); | ||
61 | |||
62 | return ME_ERRNO_SUCCESS; | ||
63 | } | ||
64 | |||
65 | int me_slock_lock(struct me_slock *slock, struct file *filep, int lock) | ||
66 | { | ||
67 | PDEBUG_LOCKS("executed.\n"); | ||
68 | |||
69 | switch (lock) { | ||
70 | |||
71 | case ME_LOCK_RELEASE: | ||
72 | spin_lock(&slock->spin_lock); | ||
73 | |||
74 | if (slock->filep == filep) | ||
75 | slock->filep = NULL; | ||
76 | |||
77 | spin_unlock(&slock->spin_lock); | ||
78 | |||
79 | break; | ||
80 | |||
81 | case ME_LOCK_SET: | ||
82 | spin_lock(&slock->spin_lock); | ||
83 | |||
84 | if (slock->count) { | ||
85 | spin_unlock(&slock->spin_lock); | ||
86 | PERROR("Subdevice is used by another process.\n"); | ||
87 | return ME_ERRNO_USED; | ||
88 | } else if (slock->filep == NULL) | ||
89 | slock->filep = filep; | ||
90 | else if (slock->filep != filep) { | ||
91 | spin_unlock(&slock->spin_lock); | ||
92 | PERROR("Subdevice is locked by another process.\n"); | ||
93 | return ME_ERRNO_LOCKED; | ||
94 | } | ||
95 | |||
96 | spin_unlock(&slock->spin_lock); | ||
97 | |||
98 | break; | ||
99 | |||
100 | case ME_LOCK_CHECK: | ||
101 | spin_lock(&slock->spin_lock); | ||
102 | |||
103 | if (slock->count) { | ||
104 | spin_unlock(&slock->spin_lock); | ||
105 | return ME_ERRNO_USED; | ||
106 | } else if ((slock->filep != NULL) && (slock->filep != filep)) { | ||
107 | spin_unlock(&slock->spin_lock); | ||
108 | return ME_ERRNO_LOCKED; | ||
109 | } | ||
110 | |||
111 | spin_unlock(&slock->spin_lock); | ||
112 | |||
113 | break; | ||
114 | |||
115 | default: | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | return ME_ERRNO_SUCCESS; | ||
120 | } | ||
121 | |||
122 | void me_slock_deinit(struct me_slock *slock) | ||
123 | { | ||
124 | PDEBUG_LOCKS("executed.\n"); | ||
125 | } | ||
126 | |||
127 | int me_slock_init(me_slock_t *slock) | ||
128 | { | ||
129 | PDEBUG_LOCKS("executed.\n"); | ||
130 | |||
131 | slock->filep = NULL; | ||
132 | slock->count = 0; | ||
133 | spin_lock_init(&slock->spin_lock); | ||
134 | |||
135 | return 0; | ||
136 | } | ||
diff --git a/drivers/staging/meilhaus/meslock.h b/drivers/staging/meilhaus/meslock.h deleted file mode 100644 index f42b25c3f622..000000000000 --- a/drivers/staging/meilhaus/meslock.h +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /** | ||
2 | * @file meslock.h | ||
3 | * | ||
4 | * @brief Provides the subdevice lock class. | ||
5 | * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _MESLOCK_H_ | ||
10 | #define _MESLOCK_H_ | ||
11 | |||
12 | #include <linux/spinlock.h> | ||
13 | |||
14 | #ifdef __KERNEL__ | ||
15 | |||
16 | /** | ||
17 | * @brief The subdevice lock class. | ||
18 | */ | ||
19 | typedef struct me_slock { | ||
20 | struct file *filep; /**< Pointer to file structure holding the subdevice. */ | ||
21 | int count; /**< Number of tasks which are inside the subdevice. */ | ||
22 | spinlock_t spin_lock; /**< Spin lock protecting the attributes from concurrent access. */ | ||
23 | } me_slock_t; | ||
24 | |||
25 | /** | ||
26 | * @brief Tries to enter a subdevice. | ||
27 | * | ||
28 | * @param slock The subdevice lock instance. | ||
29 | * @param filep The file structure identifying the calling process. | ||
30 | * | ||
31 | * @return 0 on success. | ||
32 | */ | ||
33 | int me_slock_enter(struct me_slock *slock, struct file *filep); | ||
34 | |||
35 | /** | ||
36 | * @brief Exits a subdevice. | ||
37 | * | ||
38 | * @param slock The subdevice lock instance. | ||
39 | * @param filep The file structure identifying the calling process. | ||
40 | * | ||
41 | * @return 0 on success. | ||
42 | */ | ||
43 | int me_slock_exit(struct me_slock *slock, struct file *filep); | ||
44 | |||
45 | /** | ||
46 | * @brief Tries to perform a locking action on a subdevice. | ||
47 | * | ||
48 | * @param slock The subdevice lock instance. | ||
49 | * @param filep The file structure identifying the calling process. | ||
50 | * @param The action to be done. | ||
51 | * | ||
52 | * @return 0 on success. | ||
53 | */ | ||
54 | int me_slock_lock(struct me_slock *slock, struct file *filep, int lock); | ||
55 | |||
56 | /** | ||
57 | * @brief Initializes a lock structure. | ||
58 | * | ||
59 | * @param slock The lock structure to initialize. | ||
60 | * @return 0 on success. | ||
61 | */ | ||
62 | int me_slock_init(me_slock_t * slock); | ||
63 | |||
64 | /** | ||
65 | * @brief Deinitializes a lock structure. | ||
66 | * | ||
67 | * @param slock The lock structure to deinitialize. | ||
68 | * @return 0 on success. | ||
69 | */ | ||
70 | void me_slock_deinit(me_slock_t * slock); | ||
71 | |||
72 | #endif | ||
73 | #endif | ||
diff --git a/drivers/staging/meilhaus/mesubdevice.c b/drivers/staging/meilhaus/mesubdevice.c deleted file mode 100644 index b2e956726b5f..000000000000 --- a/drivers/staging/meilhaus/mesubdevice.c +++ /dev/null | |||
@@ -1,317 +0,0 @@ | |||
1 | /** | ||
2 | * @file mesubdevice.c | ||
3 | * | ||
4 | * @brief Subdevice base class implemention. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * This file is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or | ||
13 | * (at your option) any later version. | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, | ||
16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
18 | * GNU General Public License for more details. | ||
19 | * | ||
20 | * You should have received a copy of the GNU General Public License | ||
21 | * along with this program; if not, write to the Free Software | ||
22 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
23 | */ | ||
24 | |||
25 | #ifndef __KERNEL__ | ||
26 | # define __KERNEL__ | ||
27 | #endif | ||
28 | |||
29 | #include <linux/slab.h> | ||
30 | |||
31 | #include "medefines.h" | ||
32 | #include "meerror.h" | ||
33 | |||
34 | #include "medebug.h" | ||
35 | #include "mesubdevice.h" | ||
36 | |||
37 | static int me_subdevice_io_irq_start(struct me_subdevice *subdevice, | ||
38 | struct file *filep, | ||
39 | int channel, | ||
40 | int irq_source, | ||
41 | int irq_edge, int irq_arg, int flags) | ||
42 | { | ||
43 | PDEBUG("executed.\n"); | ||
44 | return ME_ERRNO_NOT_SUPPORTED; | ||
45 | } | ||
46 | |||
47 | static int me_subdevice_io_irq_wait(struct me_subdevice *subdevice, | ||
48 | struct file *filep, | ||
49 | int channel, | ||
50 | int *irq_count, | ||
51 | int *value, int time_out, int flags) | ||
52 | { | ||
53 | PDEBUG("executed.\n"); | ||
54 | return ME_ERRNO_NOT_SUPPORTED; | ||
55 | } | ||
56 | |||
57 | static int me_subdevice_io_irq_stop(struct me_subdevice *subdevice, | ||
58 | struct file *filep, int channel, int flags) | ||
59 | { | ||
60 | PDEBUG("executed.\n"); | ||
61 | return ME_ERRNO_NOT_SUPPORTED; | ||
62 | } | ||
63 | |||
64 | static int me_subdevice_io_reset_subdevice(struct me_subdevice *subdevice, | ||
65 | struct file *filep, int flags) | ||
66 | { | ||
67 | PDEBUG("executed.\n"); | ||
68 | return ME_ERRNO_NOT_SUPPORTED; | ||
69 | } | ||
70 | |||
71 | static int me_subdevice_io_single_config(struct me_subdevice *subdevice, | ||
72 | struct file *filep, | ||
73 | int channel, | ||
74 | int single_config, | ||
75 | int ref, | ||
76 | int trig_chan, | ||
77 | int trig_type, | ||
78 | int trig_edge, int flags) | ||
79 | { | ||
80 | PDEBUG("executed.\n"); | ||
81 | return ME_ERRNO_NOT_SUPPORTED; | ||
82 | } | ||
83 | |||
84 | static int me_subdevice_io_single_read(struct me_subdevice *subdevice, | ||
85 | struct file *filep, | ||
86 | int channel, | ||
87 | int *value, int time_out, int flags) | ||
88 | { | ||
89 | PDEBUG("executed.\n"); | ||
90 | return ME_ERRNO_NOT_SUPPORTED; | ||
91 | } | ||
92 | |||
93 | static int me_subdevice_io_single_write(struct me_subdevice *subdevice, | ||
94 | struct file *filep, | ||
95 | int channel, | ||
96 | int value, int time_out, int flags) | ||
97 | { | ||
98 | PDEBUG("executed.\n"); | ||
99 | return ME_ERRNO_NOT_SUPPORTED; | ||
100 | } | ||
101 | |||
102 | static int me_subdevice_io_stream_config(struct me_subdevice *subdevice, | ||
103 | struct file *filep, | ||
104 | meIOStreamConfig_t *config_list, | ||
105 | int count, | ||
106 | meIOStreamTrigger_t *trigger, | ||
107 | int fifo_irq_threshold, int flags) | ||
108 | { | ||
109 | PDEBUG("executed.\n"); | ||
110 | return ME_ERRNO_NOT_SUPPORTED; | ||
111 | } | ||
112 | |||
113 | static int me_subdevice_io_stream_new_values(struct me_subdevice *subdevice, | ||
114 | struct file *filep, | ||
115 | int time_out, | ||
116 | int *count, int flags) | ||
117 | { | ||
118 | PDEBUG("executed.\n"); | ||
119 | return ME_ERRNO_NOT_SUPPORTED; | ||
120 | } | ||
121 | |||
122 | static int me_subdevice_io_stream_read(struct me_subdevice *subdevice, | ||
123 | struct file *filep, | ||
124 | int read_mode, | ||
125 | int *values, int *count, int flags) | ||
126 | { | ||
127 | PDEBUG("executed.\n"); | ||
128 | return ME_ERRNO_NOT_SUPPORTED; | ||
129 | } | ||
130 | |||
131 | static int me_subdevice_io_stream_start(struct me_subdevice *subdevice, | ||
132 | struct file *filep, | ||
133 | int start_mode, int time_out, int flags) | ||
134 | { | ||
135 | PDEBUG("executed.\n"); | ||
136 | return ME_ERRNO_NOT_SUPPORTED; | ||
137 | } | ||
138 | |||
139 | static int me_subdevice_io_stream_status(struct me_subdevice *subdevice, | ||
140 | struct file *filep, | ||
141 | int wait, | ||
142 | int *status, int *count, int flags) | ||
143 | { | ||
144 | PDEBUG("executed.\n"); | ||
145 | return ME_ERRNO_NOT_SUPPORTED; | ||
146 | } | ||
147 | |||
148 | static int me_subdevice_io_stream_stop(struct me_subdevice *subdevice, | ||
149 | struct file *filep, | ||
150 | int stop_mode, int flags) | ||
151 | { | ||
152 | PDEBUG("executed.\n"); | ||
153 | return ME_ERRNO_NOT_SUPPORTED; | ||
154 | } | ||
155 | |||
156 | static int me_subdevice_io_stream_write(struct me_subdevice *subdevice, | ||
157 | struct file *filep, | ||
158 | int write_mode, | ||
159 | int *values, int *count, int flags) | ||
160 | { | ||
161 | PDEBUG("executed.\n"); | ||
162 | return ME_ERRNO_NOT_SUPPORTED; | ||
163 | } | ||
164 | |||
165 | static int me_subdevice_lock_subdevice(me_subdevice_t *subdevice, | ||
166 | struct file *filep, int lock, int flags) | ||
167 | { | ||
168 | PDEBUG("executed.\n"); | ||
169 | return me_slock_lock(&subdevice->lock, filep, lock); | ||
170 | } | ||
171 | |||
172 | static int me_subdevice_query_number_channels(struct me_subdevice *subdevice, | ||
173 | int *number) | ||
174 | { | ||
175 | PDEBUG("executed.\n"); | ||
176 | return ME_ERRNO_NOT_SUPPORTED; | ||
177 | } | ||
178 | |||
179 | static int me_subdevice_query_number_ranges(struct me_subdevice *subdevice, | ||
180 | int unit, int *count) | ||
181 | { | ||
182 | PDEBUG("executed.\n"); | ||
183 | return ME_ERRNO_NOT_SUPPORTED; | ||
184 | } | ||
185 | |||
186 | static int me_subdevice_query_range_by_min_max(struct me_subdevice *subdevice, | ||
187 | int unit, | ||
188 | int *min, | ||
189 | int *max, | ||
190 | int *maxdata, int *range) | ||
191 | { | ||
192 | PDEBUG("executed.\n"); | ||
193 | return ME_ERRNO_NOT_SUPPORTED; | ||
194 | } | ||
195 | |||
196 | static int me_subdevice_query_range_info(struct me_subdevice *subdevice, | ||
197 | int range, | ||
198 | int *unit, | ||
199 | int *min, int *max, int *maxdata) | ||
200 | { | ||
201 | PDEBUG("executed.\n"); | ||
202 | return ME_ERRNO_NOT_SUPPORTED; | ||
203 | } | ||
204 | |||
205 | static int me_subdevice_query_subdevice_type(struct me_subdevice *subdevice, | ||
206 | int *type, int *subtype) | ||
207 | { | ||
208 | PDEBUG("executed.\n"); | ||
209 | return ME_ERRNO_NOT_SUPPORTED; | ||
210 | } | ||
211 | |||
212 | static int me_subdevice_query_subdevice_caps(struct me_subdevice *subdevice, | ||
213 | int *caps) | ||
214 | { | ||
215 | PDEBUG("executed.\n"); | ||
216 | *caps = 0; | ||
217 | return ME_ERRNO_SUCCESS; | ||
218 | } | ||
219 | |||
220 | static int me_subdevice_query_subdevice_caps_args(struct me_subdevice | ||
221 | *subdevice, int cap, | ||
222 | int *args, int count) | ||
223 | { | ||
224 | PDEBUG("executed.\n"); | ||
225 | return ME_ERRNO_NOT_SUPPORTED; | ||
226 | } | ||
227 | |||
228 | static int me_subdevice_query_timer(struct me_subdevice *subdevice, | ||
229 | int timer, | ||
230 | int *base_frequency, | ||
231 | long long *min_ticks, long long *max_ticks) | ||
232 | { | ||
233 | PDEBUG("executed.\n"); | ||
234 | return ME_ERRNO_NOT_SUPPORTED; | ||
235 | } | ||
236 | |||
237 | static int me_subdevice_config_load(struct me_subdevice *subdevice, | ||
238 | me_cfg_device_entry_t *config) | ||
239 | { | ||
240 | PDEBUG("executed.\n"); | ||
241 | return ME_ERRNO_SUCCESS; | ||
242 | } | ||
243 | |||
244 | static void me_subdevice_destructor(struct me_subdevice *subdevice) | ||
245 | { | ||
246 | PDEBUG("executed.\n"); | ||
247 | me_subdevice_deinit(subdevice); | ||
248 | kfree(subdevice); | ||
249 | } | ||
250 | |||
251 | int me_subdevice_init(me_subdevice_t *subdevice) | ||
252 | { | ||
253 | int err; | ||
254 | |||
255 | PDEBUG("executed.\n"); | ||
256 | |||
257 | /* Init list head */ | ||
258 | INIT_LIST_HEAD(&subdevice->list); | ||
259 | |||
260 | /* Initialize the subdevice lock instance */ | ||
261 | |||
262 | err = me_slock_init(&subdevice->lock); | ||
263 | |||
264 | if (err) { | ||
265 | PERROR("Cannot initialize subdevice lock instance.\n"); | ||
266 | return 1; | ||
267 | } | ||
268 | |||
269 | /* Subdevice base class methods */ | ||
270 | subdevice->me_subdevice_io_irq_start = me_subdevice_io_irq_start; | ||
271 | subdevice->me_subdevice_io_irq_wait = me_subdevice_io_irq_wait; | ||
272 | subdevice->me_subdevice_io_irq_stop = me_subdevice_io_irq_stop; | ||
273 | subdevice->me_subdevice_io_reset_subdevice = | ||
274 | me_subdevice_io_reset_subdevice; | ||
275 | subdevice->me_subdevice_io_single_config = | ||
276 | me_subdevice_io_single_config; | ||
277 | subdevice->me_subdevice_io_single_read = me_subdevice_io_single_read; | ||
278 | subdevice->me_subdevice_io_single_write = me_subdevice_io_single_write; | ||
279 | subdevice->me_subdevice_io_stream_config = | ||
280 | me_subdevice_io_stream_config; | ||
281 | subdevice->me_subdevice_io_stream_new_values = | ||
282 | me_subdevice_io_stream_new_values; | ||
283 | subdevice->me_subdevice_io_stream_read = me_subdevice_io_stream_read; | ||
284 | subdevice->me_subdevice_io_stream_start = me_subdevice_io_stream_start; | ||
285 | subdevice->me_subdevice_io_stream_status = | ||
286 | me_subdevice_io_stream_status; | ||
287 | subdevice->me_subdevice_io_stream_stop = me_subdevice_io_stream_stop; | ||
288 | subdevice->me_subdevice_io_stream_write = me_subdevice_io_stream_write; | ||
289 | subdevice->me_subdevice_lock_subdevice = me_subdevice_lock_subdevice; | ||
290 | subdevice->me_subdevice_query_number_channels = | ||
291 | me_subdevice_query_number_channels; | ||
292 | subdevice->me_subdevice_query_number_ranges = | ||
293 | me_subdevice_query_number_ranges; | ||
294 | subdevice->me_subdevice_query_range_by_min_max = | ||
295 | me_subdevice_query_range_by_min_max; | ||
296 | subdevice->me_subdevice_query_range_info = | ||
297 | me_subdevice_query_range_info; | ||
298 | subdevice->me_subdevice_query_subdevice_type = | ||
299 | me_subdevice_query_subdevice_type; | ||
300 | subdevice->me_subdevice_query_subdevice_caps = | ||
301 | me_subdevice_query_subdevice_caps; | ||
302 | subdevice->me_subdevice_query_subdevice_caps_args = | ||
303 | me_subdevice_query_subdevice_caps_args; | ||
304 | subdevice->me_subdevice_query_timer = me_subdevice_query_timer; | ||
305 | subdevice->me_subdevice_config_load = me_subdevice_config_load; | ||
306 | subdevice->me_subdevice_destructor = me_subdevice_destructor; | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | void me_subdevice_deinit(me_subdevice_t *subdevice) | ||
312 | { | ||
313 | PDEBUG("executed.\n"); | ||
314 | me_subdevice_io_reset_subdevice(subdevice, NULL, | ||
315 | ME_IO_RESET_SUBDEVICE_NO_FLAGS); | ||
316 | me_slock_deinit(&subdevice->lock); | ||
317 | } | ||
diff --git a/drivers/staging/meilhaus/mesubdevice.h b/drivers/staging/meilhaus/mesubdevice.h deleted file mode 100644 index 19ec2b5d96f0..000000000000 --- a/drivers/staging/meilhaus/mesubdevice.h +++ /dev/null | |||
@@ -1,197 +0,0 @@ | |||
1 | /** | ||
2 | * @file mesubdevice.h | ||
3 | * | ||
4 | * @brief Provides the subdevice base class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | #ifndef _MESUBDEVICE_H_ | ||
10 | #define _MESUBDEVICE_H_ | ||
11 | |||
12 | #include <linux/list.h> | ||
13 | |||
14 | #include "metypes.h" | ||
15 | #include "meioctl.h" | ||
16 | #include "meslock.h" | ||
17 | |||
18 | # include <linux/workqueue.h> | ||
19 | |||
20 | #ifdef __KERNEL__ | ||
21 | |||
22 | /** | ||
23 | * @brief Macro used to enter a subdevice. | ||
24 | */ | ||
25 | #define ME_SUBDEVICE_ENTER \ | ||
26 | { \ | ||
27 | int err; \ | ||
28 | err = me_slock_enter(&instance->base.lock, filep); \ | ||
29 | if(err){ \ | ||
30 | PERROR("Cannot enter subdevice.\n"); \ | ||
31 | return err; \ | ||
32 | } \ | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * @brief Macro used to exit a subdevice. | ||
37 | */ | ||
38 | #define ME_SUBDEVICE_EXIT \ | ||
39 | {\ | ||
40 | int err; \ | ||
41 | err = me_slock_exit(&instance->base.lock, filep); \ | ||
42 | if(err){ \ | ||
43 | PERROR("Cannot exit subdevice.\n"); \ | ||
44 | return err; \ | ||
45 | } \ | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * @brief The subdevice base class. | ||
50 | */ | ||
51 | typedef struct me_subdevice { | ||
52 | /* Attributes */ | ||
53 | struct list_head list; /**< Enables the subdevice to be added to a dynamic list. */ | ||
54 | me_slock_t lock; /**< Used by user application in order to lock the subdevice for exclusive usage. */ | ||
55 | |||
56 | /* Methods */ | ||
57 | int (*me_subdevice_io_irq_start) (struct me_subdevice * subdevice, | ||
58 | struct file * filep, | ||
59 | int channel, | ||
60 | int irq_source, | ||
61 | int irq_edge, int irq_arg, int flags); | ||
62 | |||
63 | int (*me_subdevice_io_irq_wait) (struct me_subdevice * subdevice, | ||
64 | struct file * filep, | ||
65 | int channel, | ||
66 | int *irq_count, | ||
67 | int *value, int time_out, int flags); | ||
68 | |||
69 | int (*me_subdevice_io_irq_stop) (struct me_subdevice * subdevice, | ||
70 | struct file * filep, | ||
71 | int channel, int flags); | ||
72 | |||
73 | int (*me_subdevice_io_reset_subdevice) (struct me_subdevice * subdevice, | ||
74 | struct file * filep, int flags); | ||
75 | |||
76 | int (*me_subdevice_io_single_config) (struct me_subdevice * subdevice, | ||
77 | struct file * filep, | ||
78 | int channel, | ||
79 | int single_config, | ||
80 | int ref, | ||
81 | int trig_chan, | ||
82 | int trig_type, | ||
83 | int trig_edge, int flags); | ||
84 | |||
85 | int (*me_subdevice_io_single_read) (struct me_subdevice * subdevice, | ||
86 | struct file * filep, | ||
87 | int channel, | ||
88 | int *value, | ||
89 | int time_out, int flags); | ||
90 | |||
91 | int (*me_subdevice_io_single_write) (struct me_subdevice * subdevice, | ||
92 | struct file * filep, | ||
93 | int channel, | ||
94 | int value, | ||
95 | int time_out, int flags); | ||
96 | |||
97 | int (*me_subdevice_io_stream_config) (struct me_subdevice * subdevice, | ||
98 | struct file * filep, | ||
99 | meIOStreamConfig_t * config_list, | ||
100 | int count, | ||
101 | meIOStreamTrigger_t * trigger, | ||
102 | int fifo_irq_threshold, | ||
103 | int flags); | ||
104 | |||
105 | int (*me_subdevice_io_stream_new_values) (struct me_subdevice * | ||
106 | subdevice, | ||
107 | struct file * filep, | ||
108 | int time_out, int *count, | ||
109 | int flags); | ||
110 | |||
111 | int (*me_subdevice_io_stream_read) (struct me_subdevice * subdevice, | ||
112 | struct file * filep, | ||
113 | int read_mode, | ||
114 | int *values, int *count, int flags); | ||
115 | |||
116 | int (*me_subdevice_io_stream_start) (struct me_subdevice * subdevice, | ||
117 | struct file * filep, | ||
118 | int start_mode, | ||
119 | int time_out, int flags); | ||
120 | |||
121 | int (*me_subdevice_io_stream_status) (struct me_subdevice * subdevice, | ||
122 | struct file * filep, | ||
123 | int wait, | ||
124 | int *status, | ||
125 | int *count, int flags); | ||
126 | |||
127 | int (*me_subdevice_io_stream_stop) (struct me_subdevice * subdevice, | ||
128 | struct file * filep, | ||
129 | int stop_mode, int flags); | ||
130 | |||
131 | int (*me_subdevice_io_stream_write) (struct me_subdevice * subdevice, | ||
132 | struct file * filep, | ||
133 | int write_mode, | ||
134 | int *values, | ||
135 | int *count, int flags); | ||
136 | |||
137 | int (*me_subdevice_lock_subdevice) (struct me_subdevice * subdevice, | ||
138 | struct file * filep, | ||
139 | int lock, int flags); | ||
140 | |||
141 | int (*me_subdevice_query_number_channels) (struct me_subdevice * | ||
142 | subdevice, int *number); | ||
143 | |||
144 | int (*me_subdevice_query_number_ranges) (struct me_subdevice * | ||
145 | subdevice, int unit, | ||
146 | int *count); | ||
147 | |||
148 | int (*me_subdevice_query_range_by_min_max) (struct me_subdevice * | ||
149 | subdevice, int unit, | ||
150 | int *min, int *max, | ||
151 | int *maxdata, int *range); | ||
152 | |||
153 | int (*me_subdevice_query_range_info) (struct me_subdevice * subdevice, | ||
154 | int range, | ||
155 | int *unit, | ||
156 | int *min, int *max, int *maxdata); | ||
157 | |||
158 | int (*me_subdevice_query_subdevice_type) (struct me_subdevice * | ||
159 | subdevice, int *type, | ||
160 | int *subtype); | ||
161 | |||
162 | int (*me_subdevice_query_subdevice_caps) (struct me_subdevice * | ||
163 | subdevice, int *caps); | ||
164 | |||
165 | int (*me_subdevice_query_subdevice_caps_args) (struct me_subdevice * | ||
166 | subdevice, int cap, | ||
167 | int *args, int count); | ||
168 | |||
169 | int (*me_subdevice_query_timer) (struct me_subdevice * subdevice, | ||
170 | int timer, | ||
171 | int *base_frequency, | ||
172 | long long *min_ticks, | ||
173 | long long *max_ticks); | ||
174 | |||
175 | int (*me_subdevice_config_load) (struct me_subdevice * subdevice, | ||
176 | me_cfg_device_entry_t * config); | ||
177 | |||
178 | void (*me_subdevice_destructor) (struct me_subdevice * subdevice); | ||
179 | } me_subdevice_t; | ||
180 | |||
181 | /** | ||
182 | * @brief Initializes a subdevice structure. | ||
183 | * | ||
184 | * @param subdevice The subdevice structure to initialize. | ||
185 | * @return 0 on success. | ||
186 | */ | ||
187 | int me_subdevice_init(me_subdevice_t * subdevice); | ||
188 | |||
189 | /** | ||
190 | * @brief Deinitializes a subdevice structure. | ||
191 | * | ||
192 | * @param subdevice The subdevice structure to initialize. | ||
193 | */ | ||
194 | void me_subdevice_deinit(me_subdevice_t * subdevice); | ||
195 | |||
196 | #endif | ||
197 | #endif | ||
diff --git a/drivers/staging/meilhaus/metempl_device.c b/drivers/staging/meilhaus/metempl_device.c deleted file mode 100644 index bdaf6df72771..000000000000 --- a/drivers/staging/meilhaus/metempl_device.c +++ /dev/null | |||
@@ -1,135 +0,0 @@ | |||
1 | /** | ||
2 | * @file metempl_device.c | ||
3 | * | ||
4 | * @brief template device class implementation. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef __KERNEL__ | ||
28 | # define __KERNEL__ | ||
29 | #endif | ||
30 | |||
31 | #ifndef MODULE | ||
32 | # define MODULE | ||
33 | #endif | ||
34 | |||
35 | #include <linux/module.h> | ||
36 | |||
37 | #include <linux/pci.h> | ||
38 | #include <linux/slab.h> | ||
39 | |||
40 | #include <meids.h> | ||
41 | #include "meerror.h" | ||
42 | #include "mecommon.h" | ||
43 | #include "meinternal.h" | ||
44 | |||
45 | #include "medebug.h" | ||
46 | #include "medevice.h" | ||
47 | #include "metempl_device.h" | ||
48 | #include "mesubdevice.h" | ||
49 | #include "metempl_sub.h" | ||
50 | |||
51 | me_device_t *metempl_pci_constructor(struct pci_dev *pci_device) | ||
52 | { | ||
53 | metempl_device_t *metempl_device; | ||
54 | me_subdevice_t *subdevice; | ||
55 | unsigned int version_idx; | ||
56 | int err; | ||
57 | int i; | ||
58 | |||
59 | PDEBUG("executed.\n"); | ||
60 | |||
61 | // Allocate structure for device instance. | ||
62 | metempl_device = kmalloc(sizeof(metempl_device_t), GFP_KERNEL); | ||
63 | |||
64 | if (!metempl_device) { | ||
65 | PERROR("Cannot get memory for device instance.\n"); | ||
66 | return NULL; | ||
67 | } | ||
68 | |||
69 | memset(metempl_device, 0, sizeof(metempl_device_t)); | ||
70 | |||
71 | // Initialize base class structure. | ||
72 | err = me_device_pci_init((me_device_t *) metempl_device, pci_device); | ||
73 | |||
74 | if (err) { | ||
75 | kfree(metempl_device); | ||
76 | PERROR("Cannot initialize device base class.\n"); | ||
77 | return NULL; | ||
78 | } | ||
79 | |||
80 | /* Get the index in the device version information table. */ | ||
81 | version_idx = | ||
82 | metempl_versions_get_device_index(metempl_device->base.info.pci. | ||
83 | device_id); | ||
84 | |||
85 | // Initialize spin lock . | ||
86 | spin_lock_init(&metempl_device->ctrl_reg_lock); | ||
87 | |||
88 | // Create subdevice instances. | ||
89 | for (i = 0; i < metempl_versions[version_idx].subdevices; i++) { | ||
90 | subdevice = | ||
91 | (me_subdevice_t *) metempl_sub_constructor(metempl_device-> | ||
92 | base.info.pci. | ||
93 | reg_bases[2], i, | ||
94 | &metempl_device-> | ||
95 | ctrl_reg_lock); | ||
96 | |||
97 | if (!subdevice) { | ||
98 | me_device_deinit((me_device_t *) metempl_device); | ||
99 | kfree(metempl_device); | ||
100 | PERROR("Cannot get memory for subdevice.\n"); | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
104 | me_slist_add_subdevice_tail(&metempl_device->base.slist, | ||
105 | subdevice); | ||
106 | } | ||
107 | |||
108 | /* Overwrite base class methods if applicable. */ | ||
109 | |||
110 | return (me_device_t *) metempl_device; | ||
111 | } | ||
112 | EXPORT_SYMBOL(metempl_pci_constructor); | ||
113 | |||
114 | // Init and exit of module. | ||
115 | |||
116 | static int __init metempl_init(void) | ||
117 | { | ||
118 | PDEBUG("executed.\n."); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static void __exit metempl_exit(void) | ||
123 | { | ||
124 | PDEBUG("executed.\n."); | ||
125 | } | ||
126 | |||
127 | module_init(metempl_init); | ||
128 | |||
129 | module_exit(metempl_exit); | ||
130 | |||
131 | // Administrative stuff for modinfo. | ||
132 | MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>"); | ||
133 | MODULE_DESCRIPTION("Device Driver Module for Template Device"); | ||
134 | MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); | ||
135 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/meilhaus/metempl_device.h b/drivers/staging/meilhaus/metempl_device.h deleted file mode 100644 index c0626e7b73a7..000000000000 --- a/drivers/staging/meilhaus/metempl_device.h +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | /** | ||
2 | * @file metempl_device.h | ||
3 | * | ||
4 | * @brief template device class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _METEMPL_DEVICE_H | ||
28 | #define _METEMPL_DEVICE_H | ||
29 | |||
30 | #include <linux/pci.h> | ||
31 | #include <linux/spinlock.h> | ||
32 | |||
33 | #include "medevice.h" | ||
34 | |||
35 | #ifdef __KERNEL__ | ||
36 | |||
37 | /** | ||
38 | * @brief Structure holding template device capabilities. | ||
39 | */ | ||
40 | typedef struct metempl_version { | ||
41 | uint16_t device_id; | ||
42 | unsigned int subdevices; | ||
43 | } metempl_version_t; | ||
44 | |||
45 | /** | ||
46 | * @brief Device capabilities. | ||
47 | */ | ||
48 | static metempl_version_t metempl_versions[] = { | ||
49 | {0xDEAD, 1}, | ||
50 | {0}, | ||
51 | }; | ||
52 | |||
53 | #define METEMPL_DEVICE_VERSIONS (ARRAY_SIZE(metempl_versions) - 1) /**< Returns the number of entries in #metempl_versions. */ | ||
54 | |||
55 | /** | ||
56 | * @brief Returns the index of the device entry in #metempl_versions. | ||
57 | * | ||
58 | * @param device_id The PCI device id of the device to query. | ||
59 | * @return The index of the device in #metempl_versions. | ||
60 | */ | ||
61 | static inline unsigned int metempl_versions_get_device_index(uint16_t device_id) | ||
62 | { | ||
63 | unsigned int i; | ||
64 | for (i = 0; i < METEMPL_DEVICE_VERSIONS; i++) | ||
65 | if (metempl_versions[i].device_id == device_id) | ||
66 | break; | ||
67 | return i; | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * @brief The template device class structure. | ||
72 | */ | ||
73 | typedef struct metempl_device { | ||
74 | me_device_t base; /**< The Meilhaus device base class. */ | ||
75 | |||
76 | /* Child class attributes. */ | ||
77 | spinlock_t ctrl_reg_lock; | ||
78 | } metempl_device_t; | ||
79 | |||
80 | /** | ||
81 | * @brief The template device class constructor. | ||
82 | * | ||
83 | * @param pci_device The pci device structure given by the PCI subsystem. | ||
84 | * | ||
85 | * @return On succes a new template device instance. \n | ||
86 | * NULL on error. | ||
87 | */ | ||
88 | me_device_t *metempl_pci_constructor(struct pci_dev *pci_device) | ||
89 | __attribute__ ((weak)); | ||
90 | |||
91 | #endif | ||
92 | #endif | ||
diff --git a/drivers/staging/meilhaus/metempl_sub.c b/drivers/staging/meilhaus/metempl_sub.c deleted file mode 100644 index b5a6a978b509..000000000000 --- a/drivers/staging/meilhaus/metempl_sub.c +++ /dev/null | |||
@@ -1,149 +0,0 @@ | |||
1 | /** | ||
2 | * @file metempl_sub.c | ||
3 | * | ||
4 | * @brief Subdevice instance. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef __KERNEL__ | ||
28 | # define __KERNEL__ | ||
29 | #endif | ||
30 | |||
31 | /* | ||
32 | * Includes | ||
33 | */ | ||
34 | #include <linux/module.h> | ||
35 | |||
36 | #include <linux/slab.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/io.h> | ||
39 | #include <linux/types.h> | ||
40 | |||
41 | #include "medefines.h" | ||
42 | #include "meinternal.h" | ||
43 | #include "meerror.h" | ||
44 | |||
45 | #include "medebug.h" | ||
46 | #include "metempl_sub_reg.h" | ||
47 | #include "metempl_sub.h" | ||
48 | |||
49 | /* | ||
50 | * Defines | ||
51 | */ | ||
52 | |||
53 | /* | ||
54 | * Functions | ||
55 | */ | ||
56 | |||
57 | static void metempl_sub_destructor(struct me_subdevice *subdevice) | ||
58 | { | ||
59 | metempl_sub_subdevice_t *instance; | ||
60 | |||
61 | PDEBUG("executed.\n"); | ||
62 | instance = (metempl_sub_subdevice_t *) subdevice; | ||
63 | |||
64 | /* Until there this was the things the default constructor does. | ||
65 | If you do not have any additional things to do you can wipe it out. */ | ||
66 | |||
67 | me_subdevice_deinit(&instance->base); | ||
68 | kfree(instance); | ||
69 | } | ||
70 | |||
71 | static int metempl_sub_query_number_channels(me_subdevice_t *subdevice, | ||
72 | int *number) | ||
73 | { | ||
74 | PDEBUG("executed.\n"); | ||
75 | *number = 0; | ||
76 | return ME_ERRNO_SUCCESS; | ||
77 | } | ||
78 | |||
79 | static int metempl_sub_query_subdevice_type(me_subdevice_t *subdevice, | ||
80 | int *type, int *subtype) | ||
81 | { | ||
82 | PDEBUG("executed.\n"); | ||
83 | *type = 0; | ||
84 | *subtype = 0; | ||
85 | return ME_ERRNO_SUCCESS; | ||
86 | } | ||
87 | |||
88 | static int metempl_sub_query_subdevice_caps(me_subdevice_t *subdevice, | ||
89 | int *caps) | ||
90 | { | ||
91 | PDEBUG("executed.\n"); | ||
92 | *caps = 0; | ||
93 | return ME_ERRNO_SUCCESS; | ||
94 | } | ||
95 | |||
96 | metempl_sub_subdevice_t *metempl_sub_constructor(uint32_t reg_base, | ||
97 | unsigned int sub_idx, | ||
98 | spinlock_t *ctrl_reg_lock) | ||
99 | { | ||
100 | metempl_sub_subdevice_t *subdevice; | ||
101 | int err; | ||
102 | |||
103 | PDEBUG("executed.\n"); | ||
104 | |||
105 | /* Allocate memory for subdevice instance */ | ||
106 | subdevice = kmalloc(sizeof(metempl_sub_subdevice_t), GFP_KERNEL); | ||
107 | |||
108 | if (!subdevice) { | ||
109 | PERROR("Cannot get memory for subdevice instance.\n"); | ||
110 | return NULL; | ||
111 | } | ||
112 | |||
113 | memset(subdevice, 0, sizeof(metempl_sub_subdevice_t)); | ||
114 | |||
115 | /* Check if subdevice index is out of range */ | ||
116 | |||
117 | if (sub_idx >= 2) { | ||
118 | PERROR("Template subdevice index is out of range.\n"); | ||
119 | kfree(subdevice); | ||
120 | return NULL; | ||
121 | } | ||
122 | |||
123 | /* Initialize subdevice base class */ | ||
124 | err = me_subdevice_init(&subdevice->base); | ||
125 | |||
126 | if (err) { | ||
127 | PERROR("Cannot initialize subdevice base class instance.\n"); | ||
128 | kfree(subdevice); | ||
129 | return NULL; | ||
130 | } | ||
131 | // Initialize spin locks. | ||
132 | spin_lock_init(&subdevice->subdevice_lock); | ||
133 | |||
134 | subdevice->ctrl_reg_lock = ctrl_reg_lock; | ||
135 | |||
136 | /* Save the subdevice index */ | ||
137 | subdevice->sub_idx = sub_idx; | ||
138 | |||
139 | /* Override base class methods. */ | ||
140 | subdevice->base.me_subdevice_destructor = metempl_sub_destructor; | ||
141 | subdevice->base.me_subdevice_query_number_channels = | ||
142 | metempl_sub_query_number_channels; | ||
143 | subdevice->base.me_subdevice_query_subdevice_type = | ||
144 | metempl_sub_query_subdevice_type; | ||
145 | subdevice->base.me_subdevice_query_subdevice_caps = | ||
146 | metempl_sub_query_subdevice_caps; | ||
147 | |||
148 | return subdevice; | ||
149 | } | ||
diff --git a/drivers/staging/meilhaus/metempl_sub.h b/drivers/staging/meilhaus/metempl_sub.h deleted file mode 100644 index 80c8af9a8c5a..000000000000 --- a/drivers/staging/meilhaus/metempl_sub.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /** | ||
2 | * @file metempl_sub.h | ||
3 | * | ||
4 | * @brief Meilhaus subdevice class. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _METEMPL_SUB_H_ | ||
28 | #define _METEMPL_SUB_H_ | ||
29 | |||
30 | #include "mesubdevice.h" | ||
31 | |||
32 | #ifdef __KERNEL__ | ||
33 | |||
34 | /** | ||
35 | * @brief The subdevice class. | ||
36 | */ | ||
37 | typedef struct metempl_sub_subdevice { | ||
38 | /* Inheritance */ | ||
39 | me_subdevice_t base; /**< The subdevice base class. */ | ||
40 | |||
41 | /* Attributes */ | ||
42 | spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ | ||
43 | spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ | ||
44 | int sub_idx; /**< The index of the subdevice on the device. */ | ||
45 | |||
46 | unsigned long ctrl_reg; /**< Register to configure the modes. */ | ||
47 | } metempl_sub_subdevice_t; | ||
48 | |||
49 | /** | ||
50 | * @brief The constructor to generate a subdevice instance. | ||
51 | * | ||
52 | * @param reg_base The register base address of the device as returned by the PCI BIOS. | ||
53 | * @param sub_idx The index of the subdevice on the device. | ||
54 | * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. | ||
55 | * | ||
56 | * @return Pointer to new instance on success.\n | ||
57 | * NULL on error. | ||
58 | */ | ||
59 | metempl_sub_subdevice_t *metempl_sub_constructor(uint32_t reg_base, | ||
60 | unsigned int sub_idx, | ||
61 | spinlock_t * ctrl_reg_lock); | ||
62 | |||
63 | #endif | ||
64 | #endif | ||
diff --git a/drivers/staging/meilhaus/metempl_sub_reg.h b/drivers/staging/meilhaus/metempl_sub_reg.h deleted file mode 100644 index 1a2cab778a12..000000000000 --- a/drivers/staging/meilhaus/metempl_sub_reg.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /** | ||
2 | * @file metempl_sub_reg.h | ||
3 | * | ||
4 | * @brief Subdevice register definitions. | ||
5 | * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
6 | * @author Guenter Gebhardt | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
11 | * | ||
12 | * This file is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | */ | ||
26 | |||
27 | #ifndef _METEMPL_SUB_REG_H_ | ||
28 | #define _METEMPL_SUB_REG_H_ | ||
29 | |||
30 | #ifdef __KERNEL__ | ||
31 | |||
32 | #define METEMPL_PORT_MODE 0x0010 /**< Configuration register. */ | ||
33 | |||
34 | #endif | ||
35 | #endif | ||
diff --git a/drivers/staging/meilhaus/metypes.h b/drivers/staging/meilhaus/metypes.h deleted file mode 100644 index 228ea15753ea..000000000000 --- a/drivers/staging/meilhaus/metypes.h +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) | ||
3 | * | ||
4 | * Source File : metypes.h | ||
5 | * Author : GG (Guenter Gebhardt) <g.gebhardt@meilhaus.de> | ||
6 | */ | ||
7 | |||
8 | #ifndef _METYPES_H_ | ||
9 | #define _METYPES_H_ | ||
10 | |||
11 | |||
12 | typedef int (*meErrorCB_t)(char *pcFunctionName, int iErrorCode); | ||
13 | |||
14 | typedef int (*meIOStreamCB_t)( | ||
15 | int iDevice, | ||
16 | int iSubdevice, | ||
17 | int iCount, | ||
18 | void *pvContext, | ||
19 | int iErrorCode); | ||
20 | |||
21 | typedef int (*meIOIrqCB_t)( | ||
22 | int iDevice, | ||
23 | int iSubdevice, | ||
24 | int iChannel, | ||
25 | int iIrqCount, | ||
26 | int iValue, | ||
27 | void *pvContext, | ||
28 | int iErrorCode); | ||
29 | |||
30 | |||
31 | typedef struct meIOSingle { | ||
32 | int iDevice; | ||
33 | int iSubdevice; | ||
34 | int iChannel; | ||
35 | int iDir; | ||
36 | int iValue; | ||
37 | int iTimeOut; | ||
38 | int iFlags; | ||
39 | int iErrno; | ||
40 | } meIOSingle_t; | ||
41 | |||
42 | |||
43 | typedef struct meIOStreamConfig { | ||
44 | int iChannel; | ||
45 | int iStreamConfig; | ||
46 | int iRef; | ||
47 | int iFlags; | ||
48 | } meIOStreamConfig_t; | ||
49 | |||
50 | |||
51 | typedef struct meIOStreamTrigger { | ||
52 | int iAcqStartTrigType; | ||
53 | int iAcqStartTrigEdge; | ||
54 | int iAcqStartTrigChan; | ||
55 | int iAcqStartTicksLow; | ||
56 | int iAcqStartTicksHigh; | ||
57 | int iAcqStartArgs[10]; | ||
58 | int iScanStartTrigType; | ||
59 | int iScanStartTicksLow; | ||
60 | int iScanStartTicksHigh; | ||
61 | int iScanStartArgs[10]; | ||
62 | int iConvStartTrigType; | ||
63 | int iConvStartTicksLow; | ||
64 | int iConvStartTicksHigh; | ||
65 | int iConvStartArgs[10]; | ||
66 | int iScanStopTrigType; | ||
67 | int iScanStopCount; | ||
68 | int iScanStopArgs[10]; | ||
69 | int iAcqStopTrigType; | ||
70 | int iAcqStopCount; | ||
71 | int iAcqStopArgs[10]; | ||
72 | int iFlags; | ||
73 | } meIOStreamTrigger_t; | ||
74 | |||
75 | |||
76 | typedef struct meIOStreamStart { | ||
77 | int iDevice; | ||
78 | int iSubdevice; | ||
79 | int iStartMode; | ||
80 | int iTimeOut; | ||
81 | int iFlags; | ||
82 | int iErrno; | ||
83 | } meIOStreamStart_t; | ||
84 | |||
85 | |||
86 | typedef struct meIOStreamStop { | ||
87 | int iDevice; | ||
88 | int iSubdevice; | ||
89 | int iStopMode; | ||
90 | int iFlags; | ||
91 | int iErrno; | ||
92 | } meIOStreamStop_t; | ||
93 | |||
94 | |||
95 | #endif | ||