]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/meilhaus/me8200_di.c
0bb4567091ccb4c3ccf381807000fb1bdc6f857b
[net-next-2.6.git] / drivers / staging / meilhaus / me8200_di.c
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 <asm/io.h>
38 #include <linux/types.h>
39 #include <linux/interrupt.h>
40 #include <linux/version.h>
41
42 #include "medefines.h"
43 #include "meerror.h"
44
45 #include "meids.h"
46 #include "medebug.h"
47 #include "me8200_reg.h"
48 #include "me8200_di_reg.h"
49 #include "me8200_di.h"
50
51 /// Defines
52 static void me8200_di_destructor(struct me_subdevice *subdevice);
53 static int me8200_di_io_irq_start(me_subdevice_t * subdevice,
54                                   struct file *filep,
55                                   int channel,
56                                   int irq_source,
57                                   int irq_edge, int irq_arg, int flags);
58 static int me8200_di_io_irq_wait(me_subdevice_t * subdevice,
59                                  struct file *filep,
60                                  int channel,
61                                  int *irq_count,
62                                  int *value, int time_out, int flags);
63 static int me8200_di_io_irq_stop(me_subdevice_t * subdevice,
64                                  struct file *filep, int channel, int flags);
65 static int me8200_di_io_single_config(me_subdevice_t * subdevice,
66                                       struct file *filep,
67                                       int channel,
68                                       int single_config,
69                                       int ref,
70                                       int trig_chan,
71                                       int trig_type, int trig_edge, int flags);
72 static int me8200_di_io_single_read(me_subdevice_t * subdevice,
73                                     struct file *filep,
74                                     int channel,
75                                     int *value, int time_out, int flags);
76 static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice,
77                                         struct file *filep, int flags);
78 static int me8200_di_query_number_channels(me_subdevice_t * subdevice,
79                                            int *number);
80 static int me8200_di_query_subdevice_type(me_subdevice_t * subdevice,
81                                           int *type, int *subtype);
82 static int me8200_di_query_subdevice_caps(me_subdevice_t * subdevice,
83                                           int *caps);
84 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
85 static irqreturn_t me8200_isr(int irq, void *dev_id);
86 #else
87 static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs);
88 #endif
89 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
90 static irqreturn_t me8200_isr_EX(int irq, void *dev_id);
91 #else
92 static irqreturn_t me8200_isr_EX(int irq, void *dev_id, struct pt_regs *regs);
93 #endif
94 static void me8200_di_check_version(me8200_di_subdevice_t * instance,
95                                     unsigned long addr);
96
97 ///Functions
98 static int me8200_di_io_irq_start(me_subdevice_t * subdevice,
99                                   struct file *filep,
100                                   int channel,
101                                   int irq_source,
102                                   int irq_edge, int irq_arg, int flags)
103 {
104         me8200_di_subdevice_t *instance;
105         int err = ME_ERRNO_SUCCESS;
106         volatile uint8_t tmp;
107         unsigned long status;
108
109         PDEBUG("executed.\n");
110
111         instance = (me8200_di_subdevice_t *) subdevice;
112
113         if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
114                 if (flags &
115                     ~(ME_IO_IRQ_START_PATTERN_FILTERING |
116                       ME_IO_IRQ_START_DIO_BYTE)) {
117                         PERROR("Invalid flag specified.\n");
118                         return ME_ERRNO_INVALID_FLAGS;
119                 }
120
121                 if (irq_edge != ME_IRQ_EDGE_NOT_USED) {
122                         PERROR("Invalid irq edge specified.\n");
123                         return ME_ERRNO_INVALID_IRQ_EDGE;
124                 }
125         } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
126                 if (flags &
127                     ~(ME_IO_IRQ_START_EXTENDED_STATUS |
128                       ME_IO_IRQ_START_DIO_BYTE)) {
129                         PERROR("Invalid flag specified.\n");
130                         return ME_ERRNO_INVALID_FLAGS;
131                 }
132
133                 if ((irq_edge != ME_IRQ_EDGE_RISING)
134                     && (irq_edge != ME_IRQ_EDGE_FALLING)
135                     && (irq_edge != ME_IRQ_EDGE_ANY)) {
136                         PERROR("Invalid irq edge specified.\n");
137                         return ME_ERRNO_INVALID_IRQ_EDGE;
138                 }
139
140                 if (!(irq_arg & 0xFF)) {
141                         PERROR("No mask specified.\n");
142                         return ME_ERRNO_INVALID_IRQ_ARG;
143                 }
144         } else {
145                 PERROR("Invalid irq source specified.\n");
146                 return ME_ERRNO_INVALID_IRQ_SOURCE;
147         }
148
149         if (channel) {
150                 PERROR("Invalid channel specified.\n");
151                 return ME_ERRNO_INVALID_CHANNEL;
152         }
153
154         ME_SUBDEVICE_ENTER;
155
156         spin_lock_irqsave(&instance->subdevice_lock, status);
157         if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
158                 outb(irq_arg, instance->compare_reg);
159                 PDEBUG_REG("compare_reg outb(0x%lX+0x%lX)=0x%x\n",
160                            instance->reg_base,
161                            instance->compare_reg - instance->reg_base, irq_arg);
162                 outb(0xFF, 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, 0xff);
166                 instance->compare_value = irq_arg;
167                 instance->filtering_flag =
168                     (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0;
169         }
170         if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
171                 outb(irq_arg, instance->mask_reg);
172                 PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n",
173                            instance->reg_base,
174                            instance->mask_reg - instance->reg_base, irq_arg);
175                 instance->filtering_flag = 0;
176         }
177
178         spin_lock(instance->irq_mode_lock);
179         tmp = inb(instance->irq_mode_reg);
180         tmp &=
181             ~(ME8200_IRQ_MODE_MASK <<
182               (ME8200_IRQ_MODE_DI_SHIFT * instance->di_idx));
183         if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
184                 tmp |=
185                     ME8200_IRQ_MODE_MASK_COMPARE << (ME8200_IRQ_MODE_DI_SHIFT *
186                                                      instance->di_idx);
187         }
188
189         if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
190                 tmp |=
191                     ME8200_IRQ_MODE_MASK_MASK << (ME8200_IRQ_MODE_DI_SHIFT *
192                                                   instance->di_idx);
193         }
194         outb(tmp, instance->irq_mode_reg);
195         PDEBUG_REG("irq_mode_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
196                    instance->irq_mode_reg - instance->reg_base, tmp);
197         spin_unlock(instance->irq_mode_lock);
198
199         spin_lock(instance->irq_ctrl_lock);
200         tmp = inb(instance->irq_ctrl_reg);
201         tmp |=
202             (ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
203              (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
204         tmp |=
205             ME8200_DI_IRQ_CTRL_BIT_ENABLE << (ME8200_DI_IRQ_CTRL_SHIFT *
206                                               instance->di_idx);
207
208         if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
209                 tmp &=
210                     ~(ME8200_DI_IRQ_CTRL_MASK_EDGE <<
211                       (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
212                 if (irq_edge == ME_IRQ_EDGE_RISING) {
213                         tmp |=
214                             ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING <<
215                             (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
216                 } else if (irq_edge == ME_IRQ_EDGE_FALLING) {
217                         tmp |=
218                             ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING <<
219                             (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
220                 } else if (irq_edge == ME_IRQ_EDGE_ANY) {
221                         tmp |=
222                             ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY <<
223                             (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx);
224                 }
225         }
226         outb(tmp, instance->irq_ctrl_reg);
227         PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
228                    instance->irq_ctrl_reg - instance->reg_base, tmp);
229         tmp &=
230             ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
231               (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
232         outb(tmp, instance->irq_ctrl_reg);
233         PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
234                    instance->irq_ctrl_reg - instance->reg_base, tmp);
235
236         instance->line_value = inb(instance->port_reg);
237         spin_unlock(instance->irq_ctrl_lock);
238
239         instance->rised = 0;
240         instance->status_value = 0;
241         instance->status_value_edges = 0;
242         instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS;
243         spin_unlock_irqrestore(&instance->subdevice_lock, status);
244         ME_SUBDEVICE_EXIT;
245
246         return err;
247 }
248
249 static int me8200_di_io_irq_wait(me_subdevice_t * subdevice,
250                                  struct file *filep,
251                                  int channel,
252                                  int *irq_count,
253                                  int *value, int time_out, int flags)
254 {
255         me8200_di_subdevice_t *instance;
256         int err = ME_ERRNO_SUCCESS;
257         long t = 0;
258         unsigned long cpu_flags;
259         int count;
260
261         PDEBUG("executed.\n");
262         PDEVELOP("PID: %d.\n", current->pid);
263
264         instance = (me8200_di_subdevice_t *) subdevice;
265
266         if (flags &
267             ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) {
268                 PERROR("Invalid flag specified.\n");
269                 return ME_ERRNO_INVALID_FLAGS;
270         }
271
272         if (channel) {
273                 PERROR("Invalid channel specified.\n");
274                 return ME_ERRNO_INVALID_CHANNEL;
275         }
276
277         if (time_out < 0) {
278                 PERROR("Invalid time_out specified.\n");
279                 return ME_ERRNO_INVALID_TIMEOUT;
280         }
281
282         if (time_out) {
283                 t = (time_out * HZ) / 1000;
284
285                 if (t == 0)
286                         t = 1;
287         }
288
289         ME_SUBDEVICE_ENTER;
290
291         if (instance->rised <= 0) {
292                 instance->rised = 0;
293                 count = instance->count;
294
295                 if (time_out) {
296                         t = wait_event_interruptible_timeout(instance->
297                                                              wait_queue,
298                                                              ((count !=
299                                                                instance->count)
300                                                               || (instance->
301                                                                   rised < 0)),
302                                                              t);
303 //                      t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t);
304                         if (t == 0) {
305                                 PERROR("Wait on interrupt timed out.\n");
306                                 err = ME_ERRNO_TIMEOUT;
307                         }
308                 } else {
309                         wait_event_interruptible(instance->wait_queue,
310                                                  ((count != instance->count)
311                                                   || (instance->rised < 0)));
312 //                      wait_event_interruptible(instance->wait_queue, (instance->rised != 0));
313                 }
314
315                 if (instance->rised < 0) {
316                         PERROR("Wait on interrupt aborted by user.\n");
317                         err = ME_ERRNO_CANCELLED;
318                 }
319         }
320
321         if (signal_pending(current)) {
322                 PERROR("Wait on interrupt aborted by signal.\n");
323                 err = ME_ERRNO_SIGNAL;
324         }
325
326         spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
327         *irq_count = instance->count;
328         if (!err) {
329                 if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) {
330                         *value = instance->status_value;
331                 } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) {
332                         *value = instance->status_value_edges;
333                 } else {        // Use default
334                         if (!instance->status_flag) {
335                                 *value = instance->status_value;
336                         } else {
337                                 *value = instance->status_value_edges;
338                         }
339                 }
340                 instance->rised = 0;
341 /*
342                         instance->status_value = 0;
343                         instance->status_value_edges = 0;
344 */
345         } else {
346                 *value = 0;
347         }
348         spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
349
350         ME_SUBDEVICE_EXIT;
351
352         return err;
353 }
354
355 static int me8200_di_io_irq_stop(me_subdevice_t * subdevice,
356                                  struct file *filep, int channel, int flags)
357 {
358         me8200_di_subdevice_t *instance;
359         uint8_t tmp;
360         unsigned long status;
361
362         PDEBUG("executed.\n");
363
364         instance = (me8200_di_subdevice_t *) subdevice;
365
366         if (flags) {
367                 PERROR("Invalid flag specified.\n");
368                 return ME_ERRNO_INVALID_FLAGS;
369         }
370
371         if (channel) {
372                 PERROR("Invalid channel specified.\n");
373                 return ME_ERRNO_INVALID_CHANNEL;
374         }
375
376         ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status);
377         spin_lock(instance->irq_ctrl_lock);
378         tmp = inb(instance->irq_ctrl_reg);
379         tmp |=
380             (ME8200_DI_IRQ_CTRL_BIT_ENABLE <<
381              (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
382         outb(tmp, instance->irq_ctrl_reg);
383         PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
384                    instance->irq_ctrl_reg - instance->reg_base, tmp);
385         tmp &=
386             ~(ME8200_DI_IRQ_CTRL_BIT_ENABLE <<
387               (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
388         tmp |=
389             (ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
390              (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
391 //                      tmp &= ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
392         outb(tmp, instance->irq_ctrl_reg);
393         PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
394                    instance->irq_ctrl_reg - instance->reg_base, tmp);
395         spin_unlock(instance->irq_ctrl_lock);
396
397         instance->rised = -1;
398         instance->status_value = 0;
399         instance->status_value_edges = 0;
400         instance->filtering_flag = 0;
401         spin_unlock_irqrestore(&instance->subdevice_lock, status);
402         wake_up_interruptible_all(&instance->wait_queue);
403
404         ME_SUBDEVICE_EXIT;
405
406         return ME_ERRNO_SUCCESS;
407 }
408
409 static int me8200_di_io_single_config(me_subdevice_t * subdevice,
410                                       struct file *filep,
411                                       int channel,
412                                       int single_config,
413                                       int ref,
414                                       int trig_chan,
415                                       int trig_type, int trig_edge, int flags)
416 {
417         me8200_di_subdevice_t *instance;
418         int err = ME_ERRNO_SUCCESS;
419         unsigned long status;
420
421         PDEBUG("executed.\n");
422
423         instance = (me8200_di_subdevice_t *) subdevice;
424
425         ME_SUBDEVICE_ENTER;
426
427         spin_lock_irqsave(&instance->subdevice_lock, status);
428
429         switch (flags) {
430         case ME_IO_SINGLE_CONFIG_NO_FLAGS:
431         case ME_IO_SINGLE_CONFIG_DIO_BYTE:
432                 if (channel == 0) {
433                         if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
434                         } else {
435                                 PERROR("Invalid port direction specified.\n");
436                                 err = ME_ERRNO_INVALID_SINGLE_CONFIG;
437                         }
438                 } else {
439                         PERROR("Invalid channel number.\n");
440                         err = ME_ERRNO_INVALID_CHANNEL;
441                 }
442                 break;
443
444         default:
445                 PERROR("Invalid flags specified.\n");
446                 err = ME_ERRNO_INVALID_FLAGS;
447         }
448
449         spin_unlock_irqrestore(&instance->subdevice_lock, status);
450
451         ME_SUBDEVICE_EXIT;
452
453         return err;
454 }
455
456 static int me8200_di_io_single_read(me_subdevice_t * subdevice,
457                                     struct file *filep,
458                                     int channel,
459                                     int *value, int time_out, int flags)
460 {
461         me8200_di_subdevice_t *instance;
462         int err = ME_ERRNO_SUCCESS;
463         unsigned long status;
464
465         PDEBUG("executed.\n");
466
467         instance = (me8200_di_subdevice_t *) subdevice;
468
469         ME_SUBDEVICE_ENTER;
470
471         spin_lock_irqsave(&instance->subdevice_lock, status);
472
473         switch (flags) {
474         case ME_IO_SINGLE_TYPE_DIO_BIT:
475                 if ((channel >= 0) && (channel < 8)) {
476                         *value = inb(instance->port_reg) & (0x1 << channel);
477                 } else {
478                         PERROR("Invalid bit number specified.\n");
479                         err = ME_ERRNO_INVALID_CHANNEL;
480                 }
481                 break;
482
483         case ME_IO_SINGLE_NO_FLAGS:
484         case ME_IO_SINGLE_TYPE_DIO_BYTE:
485                 if (channel == 0) {
486                         *value = inb(instance->port_reg);
487                 } else {
488                         PERROR("Invalid channel number.\n");
489                         err = ME_ERRNO_INVALID_CHANNEL;
490                 }
491                 break;
492
493         default:
494                 PERROR("Invalid flags specified.\n");
495                 err = ME_ERRNO_INVALID_FLAGS;
496         }
497
498         spin_unlock_irqrestore(&instance->subdevice_lock, status);
499
500         ME_SUBDEVICE_EXIT;
501
502         return err;
503 }
504
505 static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice,
506                                         struct file *filep, int flags)
507 {
508         me8200_di_subdevice_t *instance = (me8200_di_subdevice_t *) subdevice;
509
510         PDEBUG("executed.\n");
511
512         if (flags) {
513                 PERROR("Invalid flag specified.\n");
514                 return ME_ERRNO_INVALID_FLAGS;
515         }
516
517         instance->count = 0;
518         return me8200_di_io_irq_stop(subdevice, filep, 0, 0);
519 }
520
521 static int me8200_di_query_number_channels(me_subdevice_t * subdevice,
522                                            int *number)
523 {
524         PDEBUG("executed.\n");
525         *number = 8;
526         return ME_ERRNO_SUCCESS;
527 }
528
529 static int me8200_di_query_subdevice_type(me_subdevice_t * subdevice,
530                                           int *type, int *subtype)
531 {
532         PDEBUG("executed.\n");
533         *type = ME_TYPE_DI;
534         *subtype = ME_SUBTYPE_SINGLE;
535         return ME_ERRNO_SUCCESS;
536 }
537
538 static int me8200_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
539 {
540         PDEBUG("executed.\n");
541         *caps =
542             ME_CAPS_DIO_BIT_PATTERN_IRQ |
543             ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_RISING |
544             ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_FALLING |
545             ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY;
546         return ME_ERRNO_SUCCESS;
547 }
548
549 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
550 static irqreturn_t me8200_isr(int irq, void *dev_id)
551 #else
552 static irqreturn_t me8200_isr(int irq, void *dev_id, struct pt_regs *regs)
553 #endif
554 {
555         me8200_di_subdevice_t *instance;
556         uint8_t ctrl;
557         uint8_t irq_status;
558         uint8_t line_value = 0;
559         uint8_t line_status = 0;
560         uint32_t status_val = 0;
561
562         instance = (me8200_di_subdevice_t *) dev_id;
563
564         if (irq != instance->irq) {
565                 PERROR("Incorrect interrupt num: %d.\n", irq);
566                 return IRQ_NONE;
567         }
568
569         irq_status = inb(instance->irq_status_reg);
570         if (!irq_status) {
571                 PINFO
572                     ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
573                      jiffies, __FUNCTION__, instance->di_idx, irq_status);
574                 return IRQ_NONE;
575         }
576
577         PDEBUG("executed.\n");
578
579         spin_lock(&instance->subdevice_lock);
580         spin_lock(instance->irq_ctrl_lock);
581         ctrl = inb(instance->irq_ctrl_reg);
582         ctrl |=
583             ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT *
584                                              instance->di_idx);
585         outb(ctrl, instance->irq_ctrl_reg);
586         PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
587                    instance->irq_ctrl_reg - instance->reg_base, ctrl);
588         ctrl &=
589             ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR <<
590               (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx));
591         outb(ctrl, instance->irq_ctrl_reg);
592         PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
593                    instance->irq_ctrl_reg - instance->reg_base, ctrl);
594
595         line_value = inb(instance->port_reg);
596         spin_unlock(instance->irq_ctrl_lock);
597
598         line_status = ((uint8_t) instance->line_value ^ line_value);
599
600         // Make extended information.
601         status_val |= (0x00FF & (~(uint8_t) instance->line_value & line_value)) << 16;  //Raise
602         status_val |= (0x00FF & ((uint8_t) instance->line_value & ~line_value));        //Fall
603
604         instance->line_value = (int)line_value;
605
606         if (instance->rised == 0) {
607                 instance->status_value = irq_status | line_status;
608                 instance->status_value_edges = status_val;
609         } else {
610                 instance->status_value |= irq_status | line_status;
611                 instance->status_value_edges |= status_val;
612         }
613
614         if (instance->filtering_flag) { // For compare mode only.
615                 if (instance->compare_value == instance->line_value) {
616                         instance->rised = 1;
617                         instance->count++;
618                 }
619         } else {
620                 instance->rised = 1;
621                 instance->count++;
622         }
623         spin_unlock(&instance->subdevice_lock);
624
625         spin_unlock(&instance->subdevice_lock);
626
627         wake_up_interruptible_all(&instance->wait_queue);
628
629         return IRQ_HANDLED;
630 }
631
632 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
633 static irqreturn_t me8200_isr_EX(int irq, void *dev_id)
634 #else
635 static irqreturn_t me8200_isr_EX(int irq, void *dev_id, struct pt_regs *regs)
636 #endif
637 {
638         me8200_di_subdevice_t *instance;
639         uint8_t irq_status = 0;
640         uint16_t irq_status_EX = 0;
641         uint32_t status_val = 0;
642         int i, j;
643
644         instance = (me8200_di_subdevice_t *) dev_id;
645
646         if (irq != instance->irq) {
647                 PERROR("Incorrect interrupt num: %d.\n", irq);
648                 return IRQ_NONE;
649         }
650
651         PDEBUG("executed.\n");
652
653         //Reset latches. Copy status to extended registers.
654         irq_status = inb(instance->irq_status_reg);
655         PDEBUG_REG("idx=%d irq_status_reg=0x%02X\n", instance->di_idx,
656                    irq_status);
657
658         if (!irq_status) {
659                 PINFO
660                     ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n",
661                      jiffies, __FUNCTION__, instance->di_idx, irq_status);
662                 return IRQ_NONE;
663         }
664
665         irq_status_EX = inb(instance->irq_status_low_reg);
666         irq_status_EX |= (inb(instance->irq_status_high_reg) << 8);
667
668         PDEVELOP("EXTENDED REG: 0x%04x\n", irq_status_EX);
669         instance->line_value = inb(instance->port_reg);
670
671         // Format extended information.
672         for (i = 0, j = 0; i < 8; i++, j += 2) {
673                 status_val |= ((0x01 << j) & irq_status_EX) >> (j - i); //Fall
674                 status_val |= ((0x01 << (j + 1)) & irq_status_EX) << (15 - j + i);      //Raise
675         }
676
677         spin_lock(&instance->subdevice_lock);
678         if (instance->rised == 0) {
679                 instance->status_value = irq_status;
680                 instance->status_value_edges = status_val;
681         } else {
682                 instance->status_value |= irq_status;
683                 instance->status_value_edges |= status_val;
684         }
685
686         if (instance->filtering_flag) { // For compare mode only.
687                 if (instance->compare_value == instance->line_value) {
688                         instance->rised = 1;
689                         instance->count++;
690                 }
691         } else {
692                 instance->rised = 1;
693                 instance->count++;
694         }
695         spin_unlock(&instance->subdevice_lock);
696
697         wake_up_interruptible_all(&instance->wait_queue);
698
699         return IRQ_HANDLED;
700 }
701
702 static void me8200_di_destructor(struct me_subdevice *subdevice)
703 {
704         me8200_di_subdevice_t *instance;
705
706         PDEBUG("executed.\n");
707
708         instance = (me8200_di_subdevice_t *) subdevice;
709
710         free_irq(instance->irq, (void *)instance);
711         me_subdevice_deinit(&instance->base);
712         kfree(instance);
713 }
714
715 me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_regbase,
716                                              unsigned int di_idx,
717                                              int irq,
718                                              spinlock_t * irq_ctrl_lock,
719                                              spinlock_t * irq_mode_lock)
720 {
721         me8200_di_subdevice_t *subdevice;
722         int err;
723
724         PDEBUG("executed.\n");
725
726         /* Allocate memory for subdevice instance */
727         subdevice = kmalloc(sizeof(me8200_di_subdevice_t), GFP_KERNEL);
728
729         if (!subdevice) {
730                 PERROR("Cannot get memory for subdevice instance.\n");
731                 return NULL;
732         }
733
734         memset(subdevice, 0, sizeof(me8200_di_subdevice_t));
735
736         /* Initialize subdevice base class */
737         err = me_subdevice_init(&subdevice->base);
738
739         if (err) {
740                 PERROR("Cannot initialize subdevice base class instance.\n");
741                 kfree(subdevice);
742                 return NULL;
743         }
744         // Check firmware version.
745         me8200_di_check_version(subdevice,
746                                 me8200_regbase + ME8200_FIRMWARE_VERSION_REG);
747
748         // Initialize spin locks.
749         spin_lock_init(&subdevice->subdevice_lock);
750
751         subdevice->irq_ctrl_lock = irq_ctrl_lock;
752         subdevice->irq_mode_lock = irq_mode_lock;
753
754         /* Save the subdevice index. */
755         subdevice->di_idx = di_idx;
756
757         /* Initialize registers */
758         if (di_idx == 0) {
759                 subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_0_REG;
760                 subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_0_REG;
761                 subdevice->compare_reg =
762                     me8200_regbase + ME8200_DI_COMPARE_0_REG;
763                 subdevice->irq_status_reg =
764                     me8200_regbase + ME8200_DI_CHANGE_0_REG;
765
766                 subdevice->irq_status_low_reg =
767                     me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_LOW_REG;
768                 subdevice->irq_status_high_reg =
769                     me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_HIGH_REG;
770         } else if (di_idx == 1) {
771                 subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_1_REG;
772                 subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_1_REG;
773                 subdevice->compare_reg =
774                     me8200_regbase + ME8200_DI_COMPARE_1_REG;
775                 subdevice->irq_status_reg =
776                     me8200_regbase + ME8200_DI_CHANGE_1_REG;
777
778                 subdevice->irq_status_low_reg =
779                     me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_LOW_REG;
780                 subdevice->irq_status_high_reg =
781                     me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_HIGH_REG;
782         } else {
783                 PERROR("Wrong subdevice idx=%d.\n", di_idx);
784                 kfree(subdevice);
785                 return NULL;
786         }
787         subdevice->irq_ctrl_reg = me8200_regbase + ME8200_DI_IRQ_CTRL_REG;
788         subdevice->irq_mode_reg = me8200_regbase + ME8200_IRQ_MODE_REG;
789 #ifdef MEDEBUG_DEBUG_REG
790         subdevice->reg_base = me8200_regbase;
791 #endif
792
793         /* Initialize wait queue */
794         init_waitqueue_head(&subdevice->wait_queue);
795
796         /* Overload base class methods. */
797         subdevice->base.me_subdevice_io_irq_start = me8200_di_io_irq_start;
798         subdevice->base.me_subdevice_io_irq_wait = me8200_di_io_irq_wait;
799         subdevice->base.me_subdevice_io_irq_stop = me8200_di_io_irq_stop;
800         subdevice->base.me_subdevice_io_reset_subdevice =
801             me8200_di_io_reset_subdevice;
802         subdevice->base.me_subdevice_io_single_config =
803             me8200_di_io_single_config;
804         subdevice->base.me_subdevice_io_single_read = me8200_di_io_single_read;
805         subdevice->base.me_subdevice_query_number_channels =
806             me8200_di_query_number_channels;
807         subdevice->base.me_subdevice_query_subdevice_type =
808             me8200_di_query_subdevice_type;
809         subdevice->base.me_subdevice_query_subdevice_caps =
810             me8200_di_query_subdevice_caps;
811         subdevice->base.me_subdevice_destructor = me8200_di_destructor;
812
813         subdevice->rised = 0;
814         subdevice->count = 0;
815
816         /* Register interrupt service routine. */
817         subdevice->irq = irq;
818         if (subdevice->version > 0) {   // NEW
819                 err = request_irq(subdevice->irq, me8200_isr_EX,
820 #ifdef IRQF_DISABLED
821                                   IRQF_DISABLED | IRQF_SHARED,
822 #else
823                                   SA_INTERRUPT | SA_SHIRQ,
824 #endif
825                                   ME8200_NAME, (void *)subdevice);
826         } else {                //OLD
827                 err = request_irq(subdevice->irq, me8200_isr,
828 #ifdef IRQF_DISABLED
829                                   IRQF_DISABLED | IRQF_SHARED,
830 #else
831                                   SA_INTERRUPT | SA_SHIRQ,
832 #endif
833                                   ME8200_NAME, (void *)subdevice);
834         }
835
836         if (err) {
837                 PERROR("Cannot initialize subdevice base class instance.\n");
838                 kfree(subdevice);
839                 return NULL;
840         }
841         PDEBUG("Registred irq=%d.\n", subdevice->irq);
842
843         return subdevice;
844 }
845
846 static void me8200_di_check_version(me8200_di_subdevice_t * instance,
847                                     unsigned long addr)
848 {
849
850         PDEBUG("executed.\n");
851         instance->version = 0x000000FF & inb(addr);
852         PDEVELOP("me8200 firmware version: %d\n", instance->version);
853
854         /// @note Fix for wrong values in this registry.
855         if ((instance->version < 0x7) || (instance->version > 0x1F))
856                 instance->version = 0x0;
857 }