linux/drivers/staging/meilhaus/me8100_di.c
<<
>>
Prefs
   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",
 539                             jiffies, __func__, icsr);
 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",
 550                             jiffies, __func__, icsr);
 551                        return IRQ_NONE;
 552                }
 553        } else {
 554                PERROR("%s():Wrong interrupt idx=%d csr=0x%X.\n", __func__,
 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}
 694
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.