linux/drivers/staging/meilhaus/me0900_do.c
<<
>>
Prefs
   1/**
   2 * @file me0900_do.c
   3 *
   4 * @brief ME-9x digital output 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
  41#include "medefines.h"
  42#include "meinternal.h"
  43#include "meerror.h"
  44
  45#include "medebug.h"
  46#include "me0900_reg.h"
  47#include "me0900_do.h"
  48
  49/*
  50 * Defines
  51 */
  52
  53/*
  54 * Functions
  55 */
  56
  57static int me0900_do_io_reset_subdevice(struct me_subdevice *subdevice,
  58                                        struct file *filep, int flags)
  59{
  60        me0900_do_subdevice_t *instance;
  61
  62        PDEBUG("executed.\n");
  63
  64        instance = (me0900_do_subdevice_t *) subdevice;
  65
  66        if (flags) {
  67                PERROR("Invalid flag specified.\n");
  68                return ME_ERRNO_INVALID_FLAGS;
  69        }
  70
  71        ME_SUBDEVICE_ENTER;
  72
  73        spin_lock(&instance->subdevice_lock);
  74        outb(0xFF, instance->port_reg);
  75        PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base,
  76                   instance->port_reg - instance->reg_base, 0xff);
  77        spin_unlock(&instance->subdevice_lock);
  78
  79        ME_SUBDEVICE_EXIT;
  80
  81        return ME_ERRNO_SUCCESS;
  82}
  83
  84static int me0900_do_io_single_config(me_subdevice_t * subdevice,
  85                                      struct file *filep,
  86                                      int channel,
  87                                      int single_config,
  88                                      int ref,
  89                                      int trig_chan,
  90                                      int trig_type, int trig_edge, int flags)
  91{
  92        me0900_do_subdevice_t *instance;
  93        int err = ME_ERRNO_SUCCESS;
  94
  95        PDEBUG("executed.\n");
  96
  97        instance = (me0900_do_subdevice_t *) subdevice;
  98
  99        ME_SUBDEVICE_ENTER;
 100
 101        spin_lock(&instance->subdevice_lock);
 102        switch (flags) {
 103        case ME_IO_SINGLE_CONFIG_NO_FLAGS:
 104        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 105                if (channel == 0) {
 106                        if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) {
 107                        } else {
 108                                PERROR("Invalid byte direction specified.\n");
 109                                err = ME_ERRNO_INVALID_SINGLE_CONFIG;
 110                        }
 111                } else {
 112                        PERROR("Invalid byte number specified.\n");
 113                        err = ME_ERRNO_INVALID_CHANNEL;
 114                }
 115                break;
 116
 117        default:
 118                PERROR("Invalid flags specified.\n");
 119                err = ME_ERRNO_INVALID_FLAGS;
 120        }
 121        spin_unlock(&instance->subdevice_lock);
 122
 123        ME_SUBDEVICE_EXIT;
 124
 125        return err;
 126}
 127
 128static int me0900_do_io_single_read(me_subdevice_t * subdevice,
 129                                    struct file *filep,
 130                                    int channel,
 131                                    int *value, int time_out, int flags)
 132{
 133        me0900_do_subdevice_t *instance;
 134        int err = ME_ERRNO_SUCCESS;
 135
 136        PDEBUG("executed.\n");
 137
 138        instance = (me0900_do_subdevice_t *) subdevice;
 139
 140        ME_SUBDEVICE_ENTER;
 141
 142        spin_lock(&instance->subdevice_lock);
 143        switch (flags) {
 144        case ME_IO_SINGLE_TYPE_DIO_BIT:
 145                if ((channel >= 0) && (channel < 8)) {
 146                        *value = (~inb(instance->port_reg)) & (0x1 << channel);
 147                } else {
 148                        PERROR("Invalid bit number specified.\n");
 149                        err = ME_ERRNO_INVALID_CHANNEL;
 150                }
 151                break;
 152
 153        case ME_IO_SINGLE_NO_FLAGS:
 154        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 155                if (channel == 0) {
 156                        *value = ~inb(instance->port_reg);
 157                } else {
 158                        PERROR("Invalid byte number specified.\n");
 159                        err = ME_ERRNO_INVALID_CHANNEL;
 160                }
 161                break;
 162
 163        default:
 164                PERROR("Invalid flags specified.\n");
 165                err = ME_ERRNO_INVALID_FLAGS;
 166        }
 167        spin_unlock(&instance->subdevice_lock);
 168
 169        ME_SUBDEVICE_EXIT;
 170
 171        return err;
 172}
 173
 174static int me0900_do_io_single_write(me_subdevice_t * subdevice,
 175                                     struct file *filep,
 176                                     int channel,
 177                                     int value, int time_out, int flags)
 178{
 179        me0900_do_subdevice_t *instance;
 180        int err = ME_ERRNO_SUCCESS;
 181        unsigned long state;
 182
 183        PDEBUG("executed.\n");
 184
 185        instance = (me0900_do_subdevice_t *) subdevice;
 186
 187        ME_SUBDEVICE_ENTER;
 188
 189        spin_lock(&instance->subdevice_lock);
 190        switch (flags) {
 191        case ME_IO_SINGLE_TYPE_DIO_BIT:
 192                if ((channel >= 0) && (channel < 8)) {
 193                        state = inb(instance->port_reg);
 194                        state =
 195                            (!value) ? (state | (0x1 << channel)) : (state &
 196                                                                     ~(0x1 <<
 197                                                                       channel));
 198                        outb(state, instance->port_reg);
 199                } else {
 200                        PERROR("Invalid bit number specified.\n");
 201                        err = ME_ERRNO_INVALID_CHANNEL;
 202                }
 203                break;
 204
 205        case ME_IO_SINGLE_NO_FLAGS:
 206        case ME_IO_SINGLE_TYPE_DIO_BYTE:
 207                if (channel == 0) {
 208                        outb(~(value), instance->port_reg);
 209                } else {
 210                        PERROR("Invalid byte number specified.\n");
 211                        err = ME_ERRNO_INVALID_CHANNEL;
 212                }
 213                break;
 214
 215        default:
 216                PERROR("Invalid flags specified.\n");
 217                err = ME_ERRNO_INVALID_FLAGS;
 218        }
 219        spin_unlock(&instance->subdevice_lock);
 220
 221        ME_SUBDEVICE_EXIT;
 222
 223        return err;
 224}
 225
 226static int me0900_do_query_number_channels(me_subdevice_t * subdevice,
 227                                           int *number)
 228{
 229        PDEBUG("executed.\n");
 230        *number = 8;
 231        return ME_ERRNO_SUCCESS;
 232}
 233
 234static int me0900_do_query_subdevice_type(me_subdevice_t * subdevice,
 235                                          int *type, int *subtype)
 236{
 237        PDEBUG("executed.\n");
 238        *type = ME_TYPE_DO;
 239        *subtype = ME_SUBTYPE_SINGLE;
 240        return ME_ERRNO_SUCCESS;
 241}
 242
 243static int me0900_do_query_subdevice_caps(me_subdevice_t * subdevice, int *caps)
 244{
 245        PDEBUG("executed.\n");
 246        *caps = 0;
 247        return ME_ERRNO_SUCCESS;
 248}
 249
 250me0900_do_subdevice_t *me0900_do_constructor(uint32_t reg_base,
 251                                             unsigned int do_idx)
 252{
 253        me0900_do_subdevice_t *subdevice;
 254        int err;
 255
 256        PDEBUG("executed.\n");
 257
 258        /* Allocate memory for subdevice instance */
 259        subdevice = kmalloc(sizeof(me0900_do_subdevice_t), GFP_KERNEL);
 260
 261        if (!subdevice) {
 262                PERROR("Cannot get memory for subdevice instance.\n");
 263                return NULL;
 264        }
 265
 266        memset(subdevice, 0, sizeof(me0900_do_subdevice_t));
 267
 268        /* Initialize subdevice base class */
 269        err = me_subdevice_init(&subdevice->base);
 270
 271        if (err) {
 272                PERROR("Cannot initialize subdevice base class instance.\n");
 273                kfree(subdevice);
 274                return NULL;
 275        }
 276        // Initialize spin locks.
 277        spin_lock_init(&subdevice->subdevice_lock);
 278
 279        /* Save the subdevice index */
 280        subdevice->do_idx = do_idx;
 281
 282        /* Initialize registers */
 283        if (do_idx == 0) {
 284                subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
 285                subdevice->port_reg = reg_base + ME0900_PORT_A_REG;
 286                subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG;
 287                subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG;
 288        } else {
 289                subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG;
 290                subdevice->port_reg = reg_base + ME0900_PORT_B_REG;
 291                subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG;
 292                subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG;
 293        }
 294#ifdef MEDEBUG_DEBUG_REG
 295        subdevice->reg_base = reg_base;
 296#endif
 297
 298        /* Overload base class methods. */
 299        subdevice->base.me_subdevice_io_reset_subdevice =
 300            me0900_do_io_reset_subdevice;
 301        subdevice->base.me_subdevice_io_single_config =
 302            me0900_do_io_single_config;
 303        subdevice->base.me_subdevice_io_single_read = me0900_do_io_single_read;
 304        subdevice->base.me_subdevice_io_single_write =
 305            me0900_do_io_single_write;
 306        subdevice->base.me_subdevice_query_number_channels =
 307            me0900_do_query_number_channels;
 308        subdevice->base.me_subdevice_query_subdevice_type =
 309            me0900_do_query_subdevice_type;
 310        subdevice->base.me_subdevice_query_subdevice_caps =
 311            me0900_do_query_subdevice_caps;
 312
 313        return subdevice;
 314}
 315
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.