Merge branch 'simplify_PRT' into release
[sfrench/cifs-2.6.git] / drivers / staging / meilhaus / me0900_do.c
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 <asm/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 }