]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/meilhaus/me8100_di.c
staging: __FUNCTION__ is gcc-specific, use __func__
[net-next-2.6.git] / drivers / staging / meilhaus / me8100_di.c
CommitLineData
3fedd148
DK
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 <asm/io.h>
40#include <linux/types.h>
41#include <linux/interrupt.h>
42#include <linux/version.h>
43
44#include "medefines.h"
45#include "meerror.h"
46
47#include "meids.h"
48#include "medebug.h"
49#include "meplx_reg.h"
50#include "me8100_reg.h"
51#include "me8100_di_reg.h"
52#include "me8100_di.h"
53
54/*
55 * Defines
56 */
57
58/*
59 * Functions
60 */
61
62static int me8100_di_io_reset_subdevice(struct me_subdevice *subdevice,
63 struct file *filep, int flags)
64{
65 me8100_di_subdevice_t *instance;
66 unsigned short ctrl;
67 unsigned long cpu_flags;
68
69 PDEBUG("executed.\n");
70
71 instance = (me8100_di_subdevice_t *) subdevice;
72
73 if (flags) {
74 PERROR("Invalid flag specified.\n");
75 return ME_ERRNO_INVALID_FLAGS;
76 }
77
78 ME_SUBDEVICE_ENTER;
79
80 spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
81 spin_lock(instance->ctrl_reg_lock);
82 ctrl = inw(instance->ctrl_reg);
83 ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0);
84 outw(ctrl, instance->ctrl_reg);
85 PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
86 instance->ctrl_reg - instance->reg_base, ctrl);
87 spin_unlock(instance->ctrl_reg_lock);
88
89 outw(0, instance->mask_reg);
90 PDEBUG_REG("mask_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
91 instance->mask_reg - instance->reg_base, 0);
92 outw(0, instance->pattern_reg);
93 PDEBUG_REG("pattern_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
94 instance->pattern_reg - instance->reg_base, 0);
95 instance->rised = -1;
96 instance->irq_count = 0;
97 instance->filtering_flag = 0;
98 spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
99
100 outl(PLX_INTCSR_LOCAL_INT1_EN |
101 PLX_INTCSR_LOCAL_INT1_POL |
102 PLX_INTCSR_LOCAL_INT2_EN |
103 PLX_INTCSR_LOCAL_INT2_POL |
104 PLX_INTCSR_PCI_INT_EN, instance->irq_status_reg);
105 PDEBUG_REG("plx:irq_status_reg outl(0x%lX)=0x%x\n",
106 instance->irq_status_reg,
107 PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL |
108 PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL |
109 PLX_INTCSR_PCI_INT_EN);
110
111 wake_up_interruptible_all(&instance->wait_queue);
112 ME_SUBDEVICE_EXIT;
113
114 return ME_ERRNO_SUCCESS;
115}
116
117static int me8100_di_io_irq_start(me_subdevice_t * subdevice,
118 struct file *filep,
119 int channel,
120 int irq_source,
121 int irq_edge, int irq_arg, int flags)
122{
123 me8100_di_subdevice_t *instance;
124 int err = ME_ERRNO_SUCCESS;
125 uint16_t ctrl;
126 unsigned long cpu_flags;
127
128 PDEBUG("executed.\n");
129
130 instance = (me8100_di_subdevice_t *) subdevice;
131
132 if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
133 if (flags &
134 ~(ME_IO_IRQ_START_PATTERN_FILTERING |
135 ME_IO_IRQ_START_DIO_WORD)) {
136 PERROR("Invalid flag specified.\n");
137 return ME_ERRNO_INVALID_FLAGS;
138 }
139
140 if (irq_edge != ME_IRQ_EDGE_NOT_USED) {
141 PERROR("Invalid irq edge specified.\n");
142 return ME_ERRNO_INVALID_IRQ_EDGE;
143 }
144 } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
145 if (flags &
146 ~(ME_IO_IRQ_START_EXTENDED_STATUS |
147 ME_IO_IRQ_START_DIO_WORD)) {
148 PERROR("Invalid flag specified.\n");
149 return ME_ERRNO_INVALID_FLAGS;
150 }
151
152 if (irq_edge != ME_IRQ_EDGE_ANY) {
153 PERROR("Invalid irq edge specified.\n");
154 return ME_ERRNO_INVALID_IRQ_EDGE;
155 }
156
157 if (!(irq_arg & 0xFFFF)) {
158 PERROR("No mask specified.\n");
159 return ME_ERRNO_INVALID_IRQ_ARG;
160 }
161 } else {
162 PERROR("Invalid irq source specified.\n");
163 return ME_ERRNO_INVALID_IRQ_SOURCE;
164 }
165
166 if (channel) {
167 PERROR("Invalid channel specified.\n");
168 return ME_ERRNO_INVALID_CHANNEL;
169 }
170
171 ME_SUBDEVICE_ENTER;
172
173 spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
174 if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
175 outw(irq_arg, instance->pattern_reg);
176 instance->compare_value = irq_arg;
177 instance->filtering_flag =
178 (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0;
179 }
180 if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
181 outw(irq_arg, instance->mask_reg);
182 }
183
184 spin_lock(instance->ctrl_reg_lock);
185 ctrl = inw(instance->ctrl_reg);
186 ctrl |= ME8100_DIO_CTRL_BIT_INTB_0;
187 if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) {
188 ctrl &= ~ME8100_DIO_CTRL_BIT_INTB_1;
189 }
190
191 if (irq_source == ME_IRQ_SOURCE_DIO_MASK) {
192 ctrl |= ME8100_DIO_CTRL_BIT_INTB_1;
193 }
194 outw(ctrl, instance->ctrl_reg);
195 PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
196 instance->ctrl_reg - instance->reg_base, ctrl);
197 spin_unlock(instance->ctrl_reg_lock);
198
199 instance->rised = 0;
200 instance->status_value = 0;
201 instance->status_value_edges = 0;
202 instance->line_value = inw(instance->port_reg);
203 instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS;
204 spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
205
206 ME_SUBDEVICE_EXIT;
207
208 return err;
209}
210
211static int me8100_di_io_irq_wait(me_subdevice_t * subdevice,
212 struct file *filep,
213 int channel,
214 int *irq_count,
215 int *value, int time_out, int flags)
216{
217 me8100_di_subdevice_t *instance;
218 int err = ME_ERRNO_SUCCESS;
219 long t = 0;
220 unsigned long cpu_flags;
221 int count;
222
223 PDEBUG("executed.\n");
224 PDEVELOP("PID: %d.\n", current->pid);
225
226 instance = (me8100_di_subdevice_t *) subdevice;
227
228 if (flags &
229 ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) {
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 if (time_out < 0) {
240 PERROR("Invalid time_out specified.\n");
241 return ME_ERRNO_INVALID_TIMEOUT;
242 }
243
244 if (time_out) {
245 t = (time_out * HZ) / 1000;
246
247 if (t == 0)
248 t = 1;
249 }
250
251 ME_SUBDEVICE_ENTER;
252
253 if (instance->rised <= 0) {
254 instance->rised = 0;
255 count = instance->irq_count;
256
257 if (time_out) {
258 t = wait_event_interruptible_timeout(instance->
259 wait_queue,
260 ((count !=
261 instance->
262 irq_count)
263 || (instance->
264 rised < 0)),
265 t);
266// t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t);
267 if (t == 0) {
268 PERROR("Wait on interrupt timed out.\n");
269 err = ME_ERRNO_TIMEOUT;
270 }
271 } else {
272 wait_event_interruptible(instance->wait_queue,
273 ((count != instance->irq_count)
274 || (instance->rised < 0)));
275// wait_event_interruptible(instance->wait_queue, (instance->rised != 0));
276 }
277
278 if (instance->rised < 0) {
279 PERROR("Wait on interrupt aborted by user.\n");
280 err = ME_ERRNO_CANCELLED;
281 }
282 }
283
284 if (signal_pending(current)) {
285 PERROR("Wait on interrupt aborted by signal.\n");
286 err = ME_ERRNO_SIGNAL;
287 }
288
289 spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
290 *irq_count = instance->irq_count;
291 if (!err) {
292 if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) {
293 *value = instance->status_value;
294 } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) {
295 *value = instance->status_value_edges;
296 } else { // Use default
297 if (!instance->status_flag) {
298 *value = instance->status_value;
299 } else {
300 *value = instance->status_value_edges;
301 }
302 }
303 instance->rised = 0;
304/*
305 instance->status_value = 0;
306 instance->status_value_edges = 0;
307*/
308 } else {
309 *value = 0;
310 }
311 spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
312
313 ME_SUBDEVICE_EXIT;
314
315 return err;
316}
317
318static int me8100_di_io_irq_stop(me_subdevice_t * subdevice,
319 struct file *filep, int channel, int flags)
320{
321 me8100_di_subdevice_t *instance;
322 uint16_t ctrl;
323 unsigned long cpu_flags;
324
325 PDEBUG("executed.\n");
326
327 instance = (me8100_di_subdevice_t *) subdevice;
328
329 if (flags) {
330 PERROR("Invalid flag specified.\n");
331 return ME_ERRNO_INVALID_FLAGS;
332 }
333
334 if (channel) {
335 PERROR("Invalid channel specified.\n");
336 return ME_ERRNO_INVALID_CHANNEL;
337 }
338
339 ME_SUBDEVICE_ENTER;
340
341 spin_lock_irqsave(&instance->subdevice_lock, cpu_flags);
342 spin_lock(instance->ctrl_reg_lock);
343 ctrl = inw(instance->ctrl_reg);
344 ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0);
345 outw(ctrl, instance->ctrl_reg);
346 PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
347 instance->ctrl_reg - instance->reg_base, ctrl);
348 spin_unlock(instance->ctrl_reg_lock);
349 instance->rised = -1;
350 instance->status_value = 0;
351 instance->status_value_edges = 0;
352 instance->filtering_flag = 0;
353 spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags);
354 wake_up_interruptible_all(&instance->wait_queue);
355
356 ME_SUBDEVICE_EXIT;
357
358 return ME_ERRNO_SUCCESS;
359}
360
361static int me8100_di_io_single_config(me_subdevice_t * subdevice,
362 struct file *filep,
363 int channel,
364 int single_config,
365 int ref,
366 int trig_chan,
367 int trig_type, int trig_edge, int flags)
368{
369 me8100_di_subdevice_t *instance;
370 int err = ME_ERRNO_SUCCESS;
371
372 PDEBUG("executed.\n");
373
374 instance = (me8100_di_subdevice_t *) subdevice;
375
376 ME_SUBDEVICE_ENTER;
377
378 spin_lock(&instance->subdevice_lock);
379
380 switch (flags) {
381 case ME_IO_SINGLE_CONFIG_NO_FLAGS:
382 case ME_IO_SINGLE_CONFIG_DIO_WORD:
383 if (channel == 0) {
384 if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
385 } else {
386 PERROR
387 ("Invalid port configuration specified.\n");
388 err = ME_ERRNO_INVALID_SINGLE_CONFIG;
389 }
390 } else {
391 PERROR("Invalid channel number.\n");
392 err = ME_ERRNO_INVALID_CHANNEL;
393 }
394 break;
395
396 default:
397 PERROR("Invalid flags specified.\n");
398 err = ME_ERRNO_INVALID_FLAGS;
399 }
400
401 spin_unlock(&instance->subdevice_lock);
402
403 ME_SUBDEVICE_EXIT;
404
405 return err;
406}
407
408static int me8100_di_io_single_read(me_subdevice_t * subdevice,
409 struct file *filep,
410 int channel,
411 int *value, int time_out, int flags)
412{
413 me8100_di_subdevice_t *instance;
414 int err = ME_ERRNO_SUCCESS;
415
416 PDEBUG("executed.\n");
417
418 instance = (me8100_di_subdevice_t *) subdevice;
419
420 ME_SUBDEVICE_ENTER;
421
422 spin_lock(&instance->subdevice_lock);
423
424 switch (flags) {
425
426 case ME_IO_SINGLE_TYPE_DIO_BIT:
427 if ((channel >= 0) && (channel < 16)) {
428 *value = inw(instance->port_reg) & (0x1 << channel);
429 } else {
430 PERROR("Invalid bit number specified.\n");
431 err = ME_ERRNO_INVALID_CHANNEL;
432 }
433 break;
434
435 case ME_IO_SINGLE_TYPE_DIO_BYTE:
436 if (channel == 0) {
437 *value = inw(instance->port_reg) & 0xFF;
438 } else if (channel == 1) {
439 *value = (inw(instance->port_reg) >> 8) & 0xFF;
440 } else {
441 PERROR("Invalid byte number specified.\n");
442 err = ME_ERRNO_INVALID_CHANNEL;
443 }
444 break;
445
446 case ME_IO_SINGLE_NO_FLAGS:
447 case ME_IO_SINGLE_TYPE_DIO_WORD:
448 if (channel == 0) {
449 *value = inw(instance->port_reg);
450 } else {
451 PERROR("Invalid word number specified.\n");
452 err = ME_ERRNO_INVALID_CHANNEL;
453 }
454
455 break;
456
457 default:
458 PERROR("Invalid flags specified.\n");
459 err = ME_ERRNO_INVALID_FLAGS;
460 }
461
462 spin_unlock(&instance->subdevice_lock);
463
464 ME_SUBDEVICE_EXIT;
465
466 return err;
467}
468
469static int me8100_di_query_number_channels(me_subdevice_t * subdevice,
470 int *number)
471{
472 PDEBUG("executed.\n");
473 *number = 16;
474 return ME_ERRNO_SUCCESS;
475}
476
477static int me8100_di_query_subdevice_type(me_subdevice_t * subdevice,
478 int *type, int *subtype)
479{
480 PDEBUG("executed.\n");
481 *type = ME_TYPE_DI;
482 *subtype = ME_SUBTYPE_SINGLE;
483 return ME_ERRNO_SUCCESS;
484}
485
486static int me8100_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
487{
488 PDEBUG("executed.\n");
489 *caps = ME_CAPS_DIO_BIT_PATTERN_IRQ | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY;
490 return ME_ERRNO_SUCCESS;
491}
492
493static void me8100_di_destructor(struct me_subdevice *subdevice)
494{
495 me8100_di_subdevice_t *instance;
496
497 PDEBUG("executed.\n");
498
499 instance = (me8100_di_subdevice_t *) subdevice;
500
501 free_irq(instance->irq, (void *)instance);
502 me_subdevice_deinit(&instance->base);
503 kfree(instance);
504}
505
506#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)
507static irqreturn_t me8100_isr(int irq, void *dev_id)
508#else
509static irqreturn_t me8100_isr(int irq, void *dev_id, struct pt_regs *regs)
510#endif
511{
512 me8100_di_subdevice_t *instance;
513 uint32_t icsr;
514
515 uint16_t irq_status;
516 uint16_t line_value = 0;
517
518 uint32_t status_val = 0;
519
520 PDEBUG("executed.\n");
521
522 instance = (me8100_di_subdevice_t *) dev_id;
523
524 if (irq != instance->irq) {
525 PERROR("Incorrect interrupt num: %d.\n", irq);
526 return IRQ_NONE;
527 }
528
529 icsr = inl(instance->irq_status_reg);
530 if (instance->di_idx == 0) {
531
532 if ((icsr &
533 (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN |
534 PLX_INTCSR_LOCAL_INT1_EN)) !=
535 (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN |
536 PLX_INTCSR_LOCAL_INT1_EN)) {
537 PINFO
538 ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n",
d599edca 539 jiffies, __func__, icsr);
3fedd148
DK
540 return IRQ_NONE;
541 }
542 } else if (instance->di_idx == 1) {
543 if ((icsr &
544 (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN |
545 PLX_INTCSR_LOCAL_INT2_EN)) !=
546 (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN |
547 PLX_INTCSR_LOCAL_INT2_EN)) {
548 PINFO
549 ("%ld Shared interrupt. %s(): idx=1 plx:irq_status_reg=0x%04X\n",
d599edca 550 jiffies, __func__, icsr);
3fedd148
DK
551 return IRQ_NONE;
552 }
553 } else {
d599edca 554 PERROR("%s():Wrong interrupt idx=%d csr=0x%X.\n", __func__,
3fedd148
DK
555 instance->di_idx, icsr);
556 return IRQ_NONE;
557 }
558
559 PDEBUG("me8100_isr():Interrupt from idx=%d occured.\n",
560 instance->di_idx);
561 spin_lock(&instance->subdevice_lock);
562 inw(instance->irq_reset_reg);
563 line_value = inw(instance->port_reg);
564
565 irq_status = instance->line_value ^ line_value;
566
567 // Make extended information.
568 status_val |= (0x00FF & (~(uint16_t) instance->line_value & line_value)) << 16; //Raise
569 status_val |= (0x00FF & ((uint16_t) instance->line_value & ~line_value)); //Fall
570
571 instance->line_value = line_value;
572
573 if (instance->rised == 0) {
574 instance->status_value = irq_status;
575 instance->status_value_edges = status_val;
576 } else {
577 instance->status_value |= irq_status;
578 instance->status_value_edges |= status_val;
579 }
580
581 if (instance->filtering_flag) { // For compare mode only.
582 if (instance->compare_value == instance->line_value) {
583 instance->rised = 1;
584 instance->irq_count++;
585 }
586 } else {
587 instance->rised = 1;
588 instance->irq_count++;
589 }
590
591 spin_unlock(&instance->subdevice_lock);
592 wake_up_interruptible_all(&instance->wait_queue);
593
594 return IRQ_HANDLED;
595}
596
597me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base,
598 uint32_t plx_reg_base,
599 unsigned int di_idx,
600 int irq,
601 spinlock_t * ctrl_reg_lock)
602{
603 me8100_di_subdevice_t *subdevice;
604 int err;
605
606 PDEBUG("executed.\n");
607
608 /* Allocate memory for subdevice instance */
609 subdevice = kmalloc(sizeof(me8100_di_subdevice_t), GFP_KERNEL);
610
611 if (!subdevice) {
612 PERROR("Cannot get memory for subdevice instance.\n");
613 return NULL;
614 }
615
616 memset(subdevice, 0, sizeof(me8100_di_subdevice_t));
617
618 /* Initialize subdevice base class */
619 err = me_subdevice_init(&subdevice->base);
620
621 if (err) {
622 PERROR("Cannot initialize subdevice base class instance.\n");
623 kfree(subdevice);
624 return NULL;
625 }
626 // Initialize spin locks.
627 spin_lock_init(&subdevice->subdevice_lock);
628
629 subdevice->ctrl_reg_lock = ctrl_reg_lock;
630
631 /* Save the subdevice index. */
632 subdevice->di_idx = di_idx;
633
634 /* Initialize wait queue */
635 init_waitqueue_head(&subdevice->wait_queue);
636
637 /* Register interrupt service routine. */
638 subdevice->irq = irq;
639 err = request_irq(subdevice->irq, me8100_isr,
640#ifdef IRQF_DISABLED
641 IRQF_DISABLED | IRQF_SHARED,
642#else
643 SA_INTERRUPT | SA_SHIRQ,
644#endif
645 ME8100_NAME, (void *)subdevice);
646
647 if (err) {
648 PERROR("Cannot initialize subdevice base class instance.\n");
649 kfree(subdevice);
650 return NULL;
651 }
652 PINFO("Registered irq=%d.\n", subdevice->irq);
653
654 /* Initialize the registers */
655 subdevice->ctrl_reg =
656 me8100_reg_base + ME8100_CTRL_REG_A + di_idx * ME8100_REG_OFFSET;
657 subdevice->port_reg =
658 me8100_reg_base + ME8100_DI_REG_A + di_idx * ME8100_REG_OFFSET;
659 subdevice->mask_reg =
660 me8100_reg_base + ME8100_MASK_REG_A + di_idx * ME8100_REG_OFFSET;
661 subdevice->pattern_reg =
662 me8100_reg_base + ME8100_PATTERN_REG_A + di_idx * ME8100_REG_OFFSET;
663 subdevice->din_int_reg =
664 me8100_reg_base + ME8100_INT_DI_REG_A + di_idx * ME8100_REG_OFFSET;
665 subdevice->irq_reset_reg =
666 me8100_reg_base + ME8100_RES_INT_REG_A + di_idx * ME8100_REG_OFFSET;
667 subdevice->irq_status_reg = plx_reg_base + PLX_INTCSR;
668#ifdef MEDEBUG_DEBUG_REG
669 subdevice->reg_base = me8100_reg_base;
670#endif
671
672 /* Overload base class methods. */
673 subdevice->base.me_subdevice_io_irq_start = me8100_di_io_irq_start;
674 subdevice->base.me_subdevice_io_irq_wait = me8100_di_io_irq_wait;
675 subdevice->base.me_subdevice_io_irq_stop = me8100_di_io_irq_stop;
676 subdevice->base.me_subdevice_io_reset_subdevice =
677 me8100_di_io_reset_subdevice;
678 subdevice->base.me_subdevice_io_single_config =
679 me8100_di_io_single_config;
680 subdevice->base.me_subdevice_io_single_read = me8100_di_io_single_read;
681 subdevice->base.me_subdevice_query_number_channels =
682 me8100_di_query_number_channels;
683 subdevice->base.me_subdevice_query_subdevice_type =
684 me8100_di_query_subdevice_type;
685 subdevice->base.me_subdevice_query_subdevice_caps =
686 me8100_di_query_subdevice_caps;
687 subdevice->base.me_subdevice_destructor = me8100_di_destructor;
688
689 subdevice->rised = 0;
690 subdevice->irq_count = 0;
691
692 return subdevice;
693}