linux/drivers/staging/meilhaus/me0900_di.c
<<
>>
Prefs
   1/**
   2 * @file me0900_di.c
   3 *
   4 * @brief ME-9x digital input subdevice instance.
   5 * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
   6 * @author Guenter Gebhardt
   7 */
   8
   9/*
  10 * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de)
  11 *
  12 * This file is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25 */
  26
  27#ifndef __KERNEL__
  28#  define __KERNEL__
  29#endif
  30
  31/*
  32 * Includes
  33 */
  34#include <linux/module.h>
  35
  36#include <linux/slab.h>
  37#include <linux/spinlock.h>
  38#include <asm/io.h>
  39#include <linux/types.h>
  40#include <linux/interrupt.h>
  41#include <linux/version.h>
  42
  43#include "medefines.h"
  44#include "meinternal.h"
  45#include "meerror.h"
  46
  47#include "meids.h"
  48#include "medebug.h"
  49#include "meplx_reg.h"
  50#include "me0900_reg.h"
  51#include "me0900_di.h"
  52
  53/*
  54 * Defines
  55 */
  56
  57/*
  58 * Functions
  59 */
  60
  61static int me0900_di_io_reset_subdevice(struct me_subdevice *subdevice,
  62                                        struct file *filep, int flags)
  63{
  64        PDEBUG("executed.\n");
  65
  66        if (flags) {
  67                PERROR("Invalid flag specified.\n");
  68                return ME_ERRNO_INVALID_FLAGS;
  69        }
  70
  71        return ME_ERRNO_SUCCESS;
  72}
  73
  74static int me0900_di_io_single_config(me_subdevice_t * subdevice,
  75                                      struct file *filep,
  76                                      int channel,
  77                                      int single_config,
  78                                      int ref,
  79                                      int trig_chan,
  80                                      int trig_type, int trig_edge, int flags)
  81{
  82        me0900_di_subdevice_t *instance;
  83        int err = ME_ERRNO_SUCCESS;
  84
  85        PDEBUG("executed.\n");
  86
  87        instance = (me0900_di_subdevice_t *) subdevice;
  88
  89        ME_SUBDEVICE_ENTER;
  90
  91        spin_lock(&instance->subdevice_lock);
  92        switch (flags) {
  93        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
  94        case ME_IO_SINGLE_TYPE_DIO_BYTE:
  95                if (channel == 0) {
  96                        if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
  97                        } else {
  98                                PERROR("Invalid byte direction specified.\n");
  99                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 100                        }
 101                } else {
 102                        PERROR("Invalid byte number specified.\n");
 103                        err = ME_ERRNO_INVALID_CHANNEL;
 104                }
 105                break;
 106
 107        default:
 108                PERROR("Invalid flags specified.\n");
 109                err = ME_ERRNO_INVALID_FLAGS;
 110        }
 111        spin_unlock(&instance->subdevice_lock);
 112
 113        ME_SUBDEVICE_EXIT;
 114
 115        return err;
 116}
 117
 118static int me0900_di_io_single_read(me_subdevice_t * subdevice,
 119                                    struct file *filep,
 120                                    int channel,
 121                                    int *value, int time_out, int flags)
 122{
 123        me0900_di_subdevice_t *instance;
 124        int err = ME_ERRNO_SUCCESS;
 125
 126        PDEBUG("executed.\n");
 127
 128        instance = (me0900_di_subdevice_t *) subdevice;
 129
 130        ME_SUBDEVICE_ENTER;
 131
 132        spin_lock(&instance->subdevice_lock);
 133        switch (flags) {
 134        case ME_IO_SINGLE_TYPE_DIO_BIT:
 135                if ((channel >= 0) && (channel < 8)) {
 136                        *value = (~inb(instance->port_reg)) & (0x1 << channel);
 137                } else {
 138                        PERROR("Invalid bit number specified.\n");
 139                        err = ME_ERRNO_INVALID_CHANNEL;
 140                }
 141                break;
 142
 143        case ME_IO_SINGLE_NO_FLAGS:
 144        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 145                if (channel == 0) {
 146                        *value = ~inb(instance->port_reg);
 147                } else {
 148                        PERROR("Invalid byte number specified.\n");
 149                        err = ME_ERRNO_INVALID_CHANNEL;
 150                }
 151                break;
 152
 153        default:
 154                PERROR("Invalid flags specified.\n");
 155                err = ME_ERRNO_INVALID_FLAGS;
 156        }
 157        spin_unlock(&instance->subdevice_lock);
 158
 159        ME_SUBDEVICE_EXIT;
 160
 161        return err;
 162}
 163
 164static int me0900_di_query_number_channels(me_subdevice_t * subdevice,
 165                                           int *number)
 166{
 167        PDEBUG("executed.\n");
 168        *number = 8;
 169        return ME_ERRNO_SUCCESS;
 170}
 171
 172static int me0900_di_query_subdevice_type(me_subdevice_t * subdevice,
 173                                          int *type, int *subtype)
 174{
 175        PDEBUG("executed.\n");
 176        *type = ME_TYPE_DI;
 177        *subtype = ME_SUBTYPE_SINGLE;
 178        return ME_ERRNO_SUCCESS;
 179}
 180
 181static int me0900_di_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
 182{
 183        PDEBUG("executed.\n");
 184        *caps = 0;
 185        return ME_ERRNO_SUCCESS;
 186}
 187
 188me0900_di_subdevice_t *me0900_di_constructor(uint32_t reg_base,
 189                                             unsigned int di_idx)
 190{
 191        me0900_di_subdevice_t *subdevice;
 192        int err;
 193
 194        PDEBUG("executed.\n");
 195
 196        /* Allocate memory for subdevice instance */
 197        subdevice = kmalloc(sizeof(me0900_di_subdevice_t), GFP_KERNEL);
 198
 199        if (!subdevice) {
 200                PERROR("Cannot get memory for subdevice instance.\n");
 201                return NULL;
 202        }
 203
 204        memset(subdevice, 0, sizeof(me0900_di_subdevice_t));
 205
 206        /* Initialize subdevice base class */
 207        err = me_subdevice_init(&subdevice->base);
 208
 209        if (err) {
 210                PERROR("Cannot initialize subdevice base class instance.\n");
 211                kfree(subdevice);
 212                return NULL;
 213        }
 214        // Initialize spin locks.
 215        spin_lock_init(&subdevice->subdevice_lock);
 216
 217        /* Save the subdevice index. */
 218        subdevice->di_idx = di_idx;
 219
 220        /* Initialize registers */
 221        if (di_idx == 0) {
 222                subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
 223                subdevice->port_reg = reg_base + ME0900_PORT_A_REG;
 224        } else {
 225                subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
 226                subdevice->port_reg = reg_base + ME0900_PORT_B_REG;
 227        }
 228#ifdef MEDEBUG_DEBUG_REG
 229        subdevice->reg_base = reg_base;
 230#endif
 231
 232        /* Overload base class methods. */
 233        subdevice->base.me_subdevice_io_reset_subdevice =
 234            me0900_di_io_reset_subdevice;
 235        subdevice->base.me_subdevice_io_single_config =
 236            me0900_di_io_single_config;
 237        subdevice->base.me_subdevice_io_single_read = me0900_di_io_single_read;
 238        subdevice->base.me_subdevice_query_number_channels =
 239            me0900_di_query_number_channels;
 240        subdevice->base.me_subdevice_query_subdevice_type =
 241            me0900_di_query_subdevice_type;
 242        subdevice->base.me_subdevice_query_subdevice_caps =
 243            me0900_di_query_subdevice_caps;
 244
 245        return subdevice;
 246}
 247
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.