aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/meilhaus/me1600_ao.h
blob: b82bf5a1676ed9c2f3c4e569cebaa45b59ad1f30 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/**
 * @file me1600_ao.h
 *
 * @brief Meilhaus ME-1600 analog output subdevice class.
 * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
 * @author Guenter Gebhardt
 */

/*
 * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef _ME1600_AO_H_
#define _ME1600_AO_H_

# include <linux/version.h>
# include "mesubdevice.h"

# ifdef __KERNEL__

#  define ME1600_MAX_RANGES	2	/**< Specifies the maximum number of ranges in me1600_ao_subdevice_t::u_ranges und me1600_ao_subdevice_t::i_ranges. */

/**
 * @brief Defines a entry in the range table.
 */
typedef struct me1600_ao_range_entry {
	int32_t min;
	int32_t max;
} me1600_ao_range_entry_t;

typedef struct me1600_ao_timeout {
	unsigned long start_time;
	unsigned long delay;
} me1600_ao_timeout_t;

typedef struct me1600_ao_shadow {
	int count;
	unsigned long *registry;
	uint16_t *shadow;
	uint16_t *mirror;
	uint16_t synchronous;									/**< Synchronization list. */
	uint16_t trigger;										/**< Synchronization flag. */
} me1600_ao_shadow_t;

typedef enum ME1600_AO_STATUS {
	ao_status_none = 0,
	ao_status_single_configured,
	ao_status_single_run,
	ao_status_single_end,
	ao_status_last
} ME1600_AO_STATUS;

/**
 * @brief The ME-1600 analog output subdevice class.
 */
typedef struct me1600_ao_subdevice {
	/* Inheritance */
	me_subdevice_t base;									/**< The subdevice base class. */

	/* Attributes */
	int ao_idx;												/**< The index of the analog output subdevice on the device. */

	spinlock_t subdevice_lock;								/**< Spin lock to protect the subdevice from concurrent access. */
	spinlock_t *config_regs_lock;							/**< Spin lock to protect configuration registers from concurrent access. */

	int u_ranges_count;										/**< The number of voltage ranges available on this subdevice. */
	me1600_ao_range_entry_t u_ranges[ME1600_MAX_RANGES];	/**< Array holding the voltage ranges on this subdevice. */
	int i_ranges_count;										/**< The number of current ranges available on this subdevice. */
	me1600_ao_range_entry_t i_ranges[ME1600_MAX_RANGES];	/**< Array holding the current ranges on this subdevice. */

	/* Registers */
	unsigned long uni_bi_reg;								/**< Register for switching between unipoar and bipolar output mode. */
	unsigned long i_range_reg;								/**< Register for switching between ranges. */
	unsigned long sim_output_reg;							/**< Register used in order to update all channels simultaneously. */
	unsigned long current_on_reg;							/**< Register enabling current output on the fourth subdevice. */
#   ifdef PDEBUG_REG
	unsigned long reg_base;
#   endif

	ME1600_AO_STATUS status;
	me1600_ao_shadow_t *ao_regs_shadows;					/**< Addresses and shadows of output's registers. */
	spinlock_t *ao_shadows_lock;							/**< Protects the shadow's struct. */
	int mode;												/**< Mode in witch output should works. */
	wait_queue_head_t wait_queue;							/**< Wait queue to put on tasks waiting for data to arrive. */
	me1600_ao_timeout_t timeout;							/**< The timeout for start in blocking and non-blocking mode. */
	struct workqueue_struct *me1600_workqueue;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
	struct work_struct ao_control_task;
#else
	struct delayed_work ao_control_task;
#endif

	volatile int ao_control_task_flag;						/**< Flag controling reexecuting of control task */
} me1600_ao_subdevice_t;

/**
 * @brief The constructor to generate a subdevice template instance.
 *
 * @param reg_base The register base address of the device as returned by the PCI BIOS.
 * @param ao_idx The index of the analog output subdevice on the device.
 * @param current Flag indicating that analog output with #ao_idx of 3 is capable of current output.
 * @param config_regs_lock Pointer to spin lock protecting the configuration registers and from concurrent access.
 *
 * @return Pointer to new instance on success.\n
 * NULL on error.
 */
me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base,
					     unsigned int ao_idx,
					     int curr,
					     spinlock_t * config_regs_lock,
					     spinlock_t * ao_shadows_lock,
					     me1600_ao_shadow_t *
					     ao_regs_shadows,
					     struct workqueue_struct
					     *me1600_wq);

# endif	//__KERNEL__
#endif //_ME1600_AO_H_