linux/drivers/staging/meilhaus/me0600_ttli.c
<<
>>
Prefs
   1/**
   2 * @file me0600_ttli.c
   3 *
   4 * @brief ME-630 TTL 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
  42#include "medefines.h"
  43#include "meinternal.h"
  44#include "meerror.h"
  45
  46#include "medebug.h"
  47#include "me0600_ttli_reg.h"
  48#include "me0600_ttli.h"
  49
  50/*
  51 * Defines
  52 */
  53
  54/*
  55 * Functions
  56 */
  57
  58static int me0600_ttli_io_reset_subdevice(struct me_subdevice *subdevice,
  59                                          struct file *filep, int flags)
  60{
  61        if (flags) {
  62                PERROR("Invalid flag specified.\n");
  63                return ME_ERRNO_INVALID_FLAGS;
  64        }
  65
  66        PDEBUG("executed.\n");
  67        return ME_ERRNO_SUCCESS;
  68}
  69
  70static int me0600_ttli_io_single_config(me_subdevice_t * subdevice,
  71                                        struct file *filep,
  72                                        int channel,
  73                                        int single_config,
  74                                        int ref,
  75                                        int trig_chan,
  76                                        int trig_type, int trig_edge, int flags)
  77{
  78        me0600_ttli_subdevice_t *instance;
  79        int err = ME_ERRNO_SUCCESS;
  80
  81        PDEBUG("executed.\n");
  82
  83        instance = (me0600_ttli_subdevice_t *) subdevice;
  84
  85        ME_SUBDEVICE_ENTER;
  86
  87        spin_lock(&instance->subdevice_lock);
  88
  89        switch (flags) {
  90        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
  91        case ME_IO_SINGLE_CONFIG_DIO_BYTE:
  92                if (channel == 0) {
  93                        if (single_config != ME_SINGLE_CONFIG_DIO_INPUT) {
  94                                PERROR("Invalid port direction specified.\n");
  95                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
  96                        }
  97                } else {
  98                        PERROR("Invalid channel specified.\n");
  99                        err = ME_ERRNO_INVALID_CHANNEL;
 100                }
 101
 102                break;
 103
 104        default:
 105                PERROR("Invalid flags specified.\n");
 106
 107                err = ME_ERRNO_INVALID_FLAGS;
 108
 109                break;
 110        }
 111
 112        spin_unlock(&instance->subdevice_lock);
 113
 114        ME_SUBDEVICE_EXIT;
 115
 116        return err;
 117}
 118
 119static int me0600_ttli_io_single_read(me_subdevice_t * subdevice,
 120                                      struct file *filep,
 121                                      int channel,
 122                                      int *value, int time_out, int flags)
 123{
 124        me0600_ttli_subdevice_t *instance;
 125        int err = ME_ERRNO_SUCCESS;
 126
 127        PDEBUG("executed.\n");
 128
 129        instance = (me0600_ttli_subdevice_t *) subdevice;
 130
 131        ME_SUBDEVICE_ENTER;
 132
 133        spin_lock(&instance->subdevice_lock);
 134
 135        switch (flags) {
 136        case ME_IO_SINGLE_TYPE_DIO_BIT:
 137                if ((channel >= 0) && (channel < 8)) {
 138                        *value = inb(instance->port_reg) & (0x1 << channel);
 139                } else {
 140                        PERROR("Invalid bit number specified.\n");
 141                        err = ME_ERRNO_INVALID_CHANNEL;
 142                }
 143                break;
 144
 145        case ME_IO_SINGLE_NO_FLAGS:
 146        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 147                if (channel == 0) {
 148                        *value = inb(instance->port_reg);
 149                } else {
 150                        PERROR("Invalid byte number specified.\n");
 151                        err = ME_ERRNO_INVALID_CHANNEL;
 152                }
 153                break;
 154
 155        default:
 156                PERROR("Invalid flags specified.\n");
 157                err = ME_ERRNO_INVALID_FLAGS;
 158        }
 159
 160        spin_unlock(&instance->subdevice_lock);
 161
 162        ME_SUBDEVICE_EXIT;
 163
 164        return err;
 165}
 166
 167static int me0600_ttli_query_number_channels(me_subdevice_t * subdevice,
 168                                             int *number)
 169{
 170        PDEBUG("executed.\n");
 171        *number = 8;
 172        return ME_ERRNO_SUCCESS;
 173}
 174
 175static int me0600_ttli_query_subdevice_type(me_subdevice_t * subdevice,
 176                                            int *type, int *subtype)
 177{
 178        PDEBUG("executed.\n");
 179        *type = ME_TYPE_DI;
 180        *subtype = ME_SUBTYPE_SINGLE;
 181        return ME_ERRNO_SUCCESS;
 182}
 183
 184static int me0600_ttli_query_subdevice_caps(me_subdevice_t * subdevice,
 185                                            int *caps)
 186{
 187        PDEBUG("executed.\n");
 188        *caps = 0;
 189        return ME_ERRNO_SUCCESS;
 190}
 191
 192me0600_ttli_subdevice_t *me0600_ttli_constructor(uint32_t reg_base)
 193{
 194        me0600_ttli_subdevice_t *subdevice;
 195        int err;
 196
 197        PDEBUG("executed.\n");
 198
 199        /* Allocate memory for subdevice instance */
 200        subdevice = kmalloc(sizeof(me0600_ttli_subdevice_t), GFP_KERNEL);
 201
 202        if (!subdevice) {
 203                PERROR("Cannot get memory for subdevice instance.\n");
 204                return NULL;
 205        }
 206
 207        memset(subdevice, 0, sizeof(me0600_ttli_subdevice_t));
 208
 209        /* Initialize subdevice base class */
 210        err = me_subdevice_init(&subdevice->base);
 211
 212        if (err) {
 213                PERROR("Cannot initialize subdevice base class instance.\n");
 214                kfree(subdevice);
 215                return NULL;
 216        }
 217        // Initialize spin locks.
 218        spin_lock_init(&subdevice->subdevice_lock);
 219
 220        /* Save the subdevice index */
 221        subdevice->port_reg = reg_base + ME0600_TTL_INPUT_REG;
 222
 223        /* Overload base class methods. */
 224        subdevice->base.me_subdevice_io_reset_subdevice =
 225            me0600_ttli_io_reset_subdevice;
 226        subdevice->base.me_subdevice_io_single_config =
 227            me0600_ttli_io_single_config;
 228        subdevice->base.me_subdevice_io_single_read =
 229            me0600_ttli_io_single_read;
 230        subdevice->base.me_subdevice_query_number_channels =
 231            me0600_ttli_query_number_channels;
 232        subdevice->base.me_subdevice_query_subdevice_type =
 233            me0600_ttli_query_subdevice_type;
 234        subdevice->base.me_subdevice_query_subdevice_caps =
 235            me0600_ttli_query_subdevice_caps;
 236
 237        return subdevice;
 238}
 239
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.