linux/drivers/staging/meilhaus/me6000_dio.c
<<
>>
Prefs
   1/**
   2 * @file me6000_dio.c
   3 *
   4 * @brief ME-6000 digital input/output 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 "me6000_dio_reg.h"
  48#include "me6000_dio.h"
  49
  50/*
  51 * Defines
  52 */
  53
  54/*
  55 * Functions
  56 */
  57
  58static int me6000_dio_io_reset_subdevice(struct me_subdevice *subdevice,
  59                                         struct file *filep, int flags)
  60{
  61        me6000_dio_subdevice_t *instance;
  62        uint8_t mode;
  63
  64        PDEBUG("executed.\n");
  65
  66        instance = (me6000_dio_subdevice_t *) subdevice;
  67
  68        if (flags) {
  69                PERROR("Invalid flag specified.\n");
  70                return ME_ERRNO_INVALID_FLAGS;
  71        }
  72
  73        ME_SUBDEVICE_ENTER;
  74
  75        spin_lock(&instance->subdevice_lock);
  76        spin_lock(instance->ctrl_reg_lock);
  77        mode = inb(instance->ctrl_reg);
  78        mode &= ~(0x3 << (instance->dio_idx * 2));
  79        outb(mode, instance->ctrl_reg);
  80        PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  81                   instance->ctrl_reg - instance->reg_base, mode);
  82        spin_unlock(instance->ctrl_reg_lock);
  83
  84        outb(0x00, instance->port_reg);
  85        PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  86                   instance->ctrl_reg - instance->reg_base, 0x00);
  87        spin_unlock(&instance->subdevice_lock);
  88
  89        ME_SUBDEVICE_EXIT;
  90
  91        return ME_ERRNO_SUCCESS;
  92}
  93
  94static int me6000_dio_io_single_config(me_subdevice_t * subdevice,
  95                                       struct file *filep,
  96                                       int channel,
  97                                       int single_config,
  98                                       int ref,
  99                                       int trig_chan,
 100                                       int trig_type, int trig_edge, int flags)
 101{
 102        me6000_dio_subdevice_t *instance;
 103        int err = ME_ERRNO_SUCCESS;
 104        uint8_t mode;
 105        int size =
 106            flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE
 107                     | ME_IO_SINGLE_CONFIG_DIO_WORD |
 108                     ME_IO_SINGLE_CONFIG_DIO_DWORD);
 109
 110        PDEBUG("executed.\n");
 111
 112        instance = (me6000_dio_subdevice_t *) subdevice;
 113
 114        ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
 115        spin_lock(instance->ctrl_reg_lock);
 116        mode = inb(instance->ctrl_reg);
 117        switch (size) {
 118        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 119        case ME_IO_SINGLE_CONFIG_DIO_BYTE:
 120                if (channel == 0) {
 121                        if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) {
 122                                mode &=
 123                                    ~((ME6000_DIO_CTRL_BIT_MODE_0 |
 124                                       ME6000_DIO_CTRL_BIT_MODE_1) <<
 125                                      (instance->dio_idx * 2));
 126                        } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
 127                                mode &=
 128                                    ~((ME6000_DIO_CTRL_BIT_MODE_0 |
 129                                       ME6000_DIO_CTRL_BIT_MODE_1) <<
 130                                      (instance->dio_idx * 2));
 131                                mode |=
 132                                    ME6000_DIO_CTRL_BIT_MODE_0 << (instance->
 133                                                                   dio_idx * 2);
 134                        } else {
 135                                PERROR
 136                                    ("Invalid port configuration specified.\n");
 137                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 138                        }
 139                } else {
 140                        PERROR("Invalid channel number.\n");
 141                        err = ME_ERRNO_INVALID_CHANNEL;
 142                }
 143                break;
 144
 145        default:
 146                PERROR("Invalid flags.\n");
 147                err = ME_ERRNO_INVALID_FLAGS;
 148        }
 149
 150        if (!err) {
 151                outb(mode, instance->ctrl_reg);
 152                PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n",
 153                           instance->reg_base,
 154                           instance->ctrl_reg - instance->reg_base, mode);
 155        }
 156        spin_unlock(instance->ctrl_reg_lock);
 157        spin_unlock(&instance->subdevice_lock);
 158
 159        ME_SUBDEVICE_EXIT;
 160
 161        return err;
 162}
 163
 164static int me6000_dio_io_single_read(me_subdevice_t * subdevice,
 165                                     struct file *filep,
 166                                     int channel,
 167                                     int *value, int time_out, int flags)
 168{
 169        me6000_dio_subdevice_t *instance;
 170        int err = ME_ERRNO_SUCCESS;
 171        uint8_t mode;
 172
 173        PDEBUG("executed.\n");
 174
 175        instance = (me6000_dio_subdevice_t *) subdevice;
 176
 177        ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
 178        spin_lock(instance->ctrl_reg_lock);
 179        switch (flags) {
 180        case ME_IO_SINGLE_TYPE_DIO_BIT:
 181                if ((channel >= 0) && (channel < 8)) {
 182                        mode =
 183                            inb(instance->
 184                                ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
 185                                              ME6000_DIO_CTRL_BIT_MODE_1) <<
 186                                             (instance->dio_idx * 2));
 187                        if ((mode ==
 188                             (ME6000_DIO_CTRL_BIT_MODE_0 <<
 189                              (instance->dio_idx * 2))) || !mode) {
 190                                *value =
 191                                    inb(instance->port_reg) & (0x1 << channel);
 192                        } else {
 193                                PERROR("Port not in output or input mode.\n");
 194                                err = ME_ERRNO_PREVIOUS_CONFIG;
 195                        }
 196                } else {
 197                        PERROR("Invalid bit number specified.\n");
 198                        err = ME_ERRNO_INVALID_CHANNEL;
 199                }
 200                break;
 201
 202        case ME_IO_SINGLE_NO_FLAGS:
 203        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 204                if (channel == 0) {
 205                        mode =
 206                            inb(instance->
 207                                ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
 208                                              ME6000_DIO_CTRL_BIT_MODE_1) <<
 209                                             (instance->dio_idx * 2));
 210                        if ((mode ==
 211                             (ME6000_DIO_CTRL_BIT_MODE_0 <<
 212                              (instance->dio_idx * 2))) || !mode) {
 213                                *value = inb(instance->port_reg) & 0x00FF;
 214                        } else {
 215                                PERROR("Port not in output or input mode.\n");
 216                                err = ME_ERRNO_PREVIOUS_CONFIG;
 217                        }
 218                } else {
 219                        PERROR("Invalid byte number specified.\n");
 220                        err = ME_ERRNO_INVALID_CHANNEL;
 221                }
 222                break;
 223
 224        default:
 225                PERROR("Invalid flags specified.\n");
 226                err = ME_ERRNO_INVALID_FLAGS;
 227        }
 228        spin_unlock(instance->ctrl_reg_lock);
 229        spin_unlock(&instance->subdevice_lock);
 230
 231        ME_SUBDEVICE_EXIT;
 232
 233        return err;
 234}
 235
 236static int me6000_dio_io_single_write(me_subdevice_t * subdevice,
 237                                      struct file *filep,
 238                                      int channel,
 239                                      int value, int time_out, int flags)
 240{
 241        me6000_dio_subdevice_t *instance;
 242        int err = ME_ERRNO_SUCCESS;
 243        uint8_t mode;
 244        uint8_t byte;
 245
 246        PDEBUG("executed.\n");
 247
 248        instance = (me6000_dio_subdevice_t *) subdevice;
 249
 250        ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock);
 251        spin_lock(instance->ctrl_reg_lock);
 252        switch (flags) {
 253        case ME_IO_SINGLE_TYPE_DIO_BIT:
 254                if ((channel >= 0) && (channel < 8)) {
 255                        mode =
 256                            inb(instance->
 257                                ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
 258                                              ME6000_DIO_CTRL_BIT_MODE_1) <<
 259                                             (instance->dio_idx * 2));
 260
 261                        if (mode ==
 262                            (ME6000_DIO_CTRL_BIT_MODE_0 <<
 263                             (instance->dio_idx * 2))) {
 264                                byte = inb(instance->port_reg) & 0x00FF;
 265
 266                                if (value)
 267                                        byte |= 0x1 << channel;
 268                                else
 269                                        byte &= ~(0x1 << channel);
 270
 271                                outb(byte, instance->port_reg);
 272                        } else {
 273                                PERROR("Port not in output or input mode.\n");
 274                                err = ME_ERRNO_PREVIOUS_CONFIG;
 275                        }
 276                } else {
 277                        PERROR("Invalid bit number specified.\n");
 278                        err = ME_ERRNO_INVALID_CHANNEL;
 279                }
 280                break;
 281
 282        case ME_IO_SINGLE_NO_FLAGS:
 283        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 284                if (channel == 0) {
 285                        mode =
 286                            inb(instance->
 287                                ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 |
 288                                              ME6000_DIO_CTRL_BIT_MODE_1) <<
 289                                             (instance->dio_idx * 2));
 290
 291                        if (mode ==
 292                            (ME6000_DIO_CTRL_BIT_MODE_0 <<
 293                             (instance->dio_idx * 2))) {
 294                                outb(value, instance->port_reg);
 295                        } else {
 296                                PERROR("Port not in output or input mode.\n");
 297                                err = ME_ERRNO_PREVIOUS_CONFIG;
 298                        }
 299                } else {
 300                        PERROR("Invalid byte number specified.\n");
 301                        err = ME_ERRNO_INVALID_CHANNEL;
 302                }
 303                break;
 304
 305        default:
 306                PERROR("Invalid flags specified.\n");
 307                err = ME_ERRNO_INVALID_FLAGS;
 308        }
 309        spin_unlock(instance->ctrl_reg_lock);
 310        spin_unlock(&instance->subdevice_lock);
 311
 312        ME_SUBDEVICE_EXIT;
 313
 314        return err;
 315}
 316
 317static int me6000_dio_query_number_channels(me_subdevice_t * subdevice,
 318                                            int *number)
 319{
 320        PDEBUG("executed.\n");
 321        *number = 8;
 322        return ME_ERRNO_SUCCESS;
 323}
 324
 325static int me6000_dio_query_subdevice_type(me_subdevice_t * subdevice,
 326                                           int *type, int *subtype)
 327{
 328        PDEBUG("executed.\n");
 329        *type = ME_TYPE_DIO;
 330        *subtype = ME_SUBTYPE_SINGLE;
 331        return ME_ERRNO_SUCCESS;
 332}
 333
 334static int me6000_dio_query_subdevice_caps(me_subdevice_t * subdevice,
 335                                           int *caps)
 336{
 337        PDEBUG("executed.\n");
 338        *caps = ME_CAPS_DIO_DIR_BYTE;
 339        return ME_ERRNO_SUCCESS;
 340}
 341
 342me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base,
 343                                               unsigned int dio_idx,
 344                                               spinlock_t * ctrl_reg_lock)
 345{
 346        me6000_dio_subdevice_t *subdevice;
 347        int err;
 348
 349        PDEBUG("executed.\n");
 350
 351        /* Allocate memory for subdevice instance */
 352        subdevice = kmalloc(sizeof(me6000_dio_subdevice_t), GFP_KERNEL);
 353
 354        if (!subdevice) {
 355                PERROR("Cannot get memory for subdevice instance.\n");
 356                return NULL;
 357        }
 358
 359        memset(subdevice, 0, sizeof(me6000_dio_subdevice_t));
 360
 361        /* Initialize subdevice base class */
 362        err = me_subdevice_init(&subdevice->base);
 363        if (err) {
 364                PERROR("Cannot initialize subdevice base class instance.\n");
 365                kfree(subdevice);
 366                return NULL;
 367        }
 368
 369        /* Set the subdevice ports */
 370        subdevice->ctrl_reg = reg_base + ME6000_DIO_CTRL_REG;
 371        switch (dio_idx) {
 372        case 0:
 373                subdevice->port_reg = reg_base + ME6000_DIO_PORT_0_REG;
 374                break;
 375        case 1:
 376                subdevice->port_reg = reg_base + ME6000_DIO_PORT_1_REG;
 377                break;
 378        default:
 379                err = ME_ERRNO_INVALID_SUBDEVICE;
 380        }
 381
 382        if (err) {
 383                PERROR("Cannot initialize subdevice base class instance.\n");
 384                kfree(subdevice);
 385                return NULL;
 386        }
 387        // Initialize spin locks.
 388        spin_lock_init(&subdevice->subdevice_lock);
 389
 390        subdevice->ctrl_reg_lock = ctrl_reg_lock;
 391
 392        /* Save digital i/o index */
 393        subdevice->dio_idx = dio_idx;
 394
 395#ifdef MEDEBUG_DEBUG_REG
 396        subdevice->reg_base = reg_base;
 397#endif
 398
 399        /* Overload base class methods. */
 400        subdevice->base.me_subdevice_io_reset_subdevice =
 401            me6000_dio_io_reset_subdevice;
 402        subdevice->base.me_subdevice_io_single_config =
 403            me6000_dio_io_single_config;
 404        subdevice->base.me_subdevice_io_single_read = me6000_dio_io_single_read;
 405        subdevice->base.me_subdevice_io_single_write =
 406            me6000_dio_io_single_write;
 407        subdevice->base.me_subdevice_query_number_channels =
 408            me6000_dio_query_number_channels;
 409        subdevice->base.me_subdevice_query_subdevice_type =
 410            me6000_dio_query_subdevice_type;
 411        subdevice->base.me_subdevice_query_subdevice_caps =
 412            me6000_dio_query_subdevice_caps;
 413
 414        return subdevice;
 415}
 416
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.