Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 }
360 
  This page was automatically generated by the LXR engine.