linux/drivers/staging/meilhaus/me6000_device.c
<<
>>
Prefs
   1/**
   2 * @file me6000_device.c
   3 *
   4 * @brief Device class template implementation.
   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#ifndef MODULE
  33#  define MODULE
  34#endif
  35
  36#include <linux/module.h>
  37
  38#include <linux/pci.h>
  39#include <linux/slab.h>
  40
  41#include "meids.h"
  42#include "meerror.h"
  43#include "mecommon.h"
  44#include "meinternal.h"
  45
  46#include "mefirmware.h"
  47
  48#include "mesubdevice.h"
  49#include "medebug.h"
  50#include "medevice.h"
  51#include "me6000_reg.h"
  52#include "me6000_device.h"
  53#include "meplx_reg.h"
  54#include "me6000_dio.h"
  55#include "me6000_ao.h"
  56
  57/**
  58 * @brief Global variable.
  59 * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts).
  60 */
  61static struct workqueue_struct *me6000_workqueue;
  62
  63me_device_t *me6000_pci_constructor(struct pci_dev *pci_device)
  64{
  65        me6000_device_t *me6000_device;
  66        me_subdevice_t *subdevice;
  67        unsigned int version_idx;
  68        int err;
  69        int i;
  70        int high_range = 0;
  71        int fifo;
  72
  73        PDEBUG("executed.\n");
  74
  75        // Allocate structure for device instance.
  76        me6000_device = kmalloc(sizeof(me6000_device_t), GFP_KERNEL);
  77
  78        if (!me6000_device) {
  79                PERROR("Cannot get memory for device instance.\n");
  80                return NULL;
  81        }
  82
  83        memset(me6000_device, 0, sizeof(me6000_device_t));
  84
  85        // Initialize base class structure.
  86        err = me_device_pci_init((me_device_t *) me6000_device, pci_device);
  87
  88        if (err) {
  89                kfree(me6000_device);
  90                PERROR("Cannot initialize device base class.\n");
  91                return NULL;
  92        }
  93
  94        /* Download the xilinx firmware */
  95        err = me_xilinx_download(me6000_device->base.info.pci.reg_bases[1],
  96                                 me6000_device->base.info.pci.reg_bases[2],
  97                                 &pci_device->dev, "me6000.bin");
  98
  99        if (err) {
 100                me_device_deinit((me_device_t *) me6000_device);
 101                kfree(me6000_device);
 102                PERROR("Can't download firmware.\n");
 103                return NULL;
 104        }
 105
 106        /* Get the index in the device version information table. */
 107        version_idx =
 108            me6000_versions_get_device_index(me6000_device->base.info.pci.
 109                                             device_id);
 110
 111        // Initialize spin lock .
 112        spin_lock_init(&me6000_device->preload_reg_lock);
 113        spin_lock_init(&me6000_device->dio_ctrl_reg_lock);
 114
 115        /* Create digital input/output instances. */
 116        for (i = 0; i < me6000_versions[version_idx].dio_subdevices; i++) {
 117                subdevice =
 118                    (me_subdevice_t *) me6000_dio_constructor(me6000_device->
 119                                                              base.info.pci.
 120                                                              reg_bases[3], i,
 121                                                              &me6000_device->
 122                                                              dio_ctrl_reg_lock);
 123
 124                if (!subdevice) {
 125                        me_device_deinit((me_device_t *) me6000_device);
 126                        kfree(me6000_device);
 127                        PERROR("Cannot get memory for subdevice.\n");
 128                        return NULL;
 129                }
 130
 131                me_slist_add_subdevice_tail(&me6000_device->base.slist,
 132                                            subdevice);
 133        }
 134
 135        /* Create analog output instances. */
 136        for (i = 0; i < me6000_versions[version_idx].ao_subdevices; i++) {
 137                high_range = ((i == 8)
 138                              &&
 139                              ((me6000_device->base.info.pci.device_id ==
 140                                PCI_DEVICE_ID_MEILHAUS_ME6359)
 141                               || (me6000_device->base.info.pci.device_id ==
 142                                   PCI_DEVICE_ID_MEILHAUS_ME6259)
 143                              )
 144                    )? 1 : 0;
 145
 146                fifo =
 147                    (i <
 148                     me6000_versions[version_idx].
 149                     ao_fifo) ? ME6000_AO_HAS_FIFO : 0x0;
 150                fifo |= (i < 4) ? ME6000_AO_EXTRA_HARDWARE : 0x0;
 151
 152                subdevice =
 153                    (me_subdevice_t *) me6000_ao_constructor(me6000_device->
 154                                                             base.info.pci.
 155                                                             reg_bases[2],
 156                                                             &me6000_device->
 157                                                             preload_reg_lock,
 158                                                             &me6000_device->
 159                                                             preload_flags,
 160                                                             &me6000_device->
 161                                                             triggering_flags,
 162                                                             i, fifo,
 163                                                             me6000_device->
 164                                                             base.irq,
 165                                                             high_range,
 166                                                             me6000_workqueue);
 167
 168                if (!subdevice) {
 169                        me_device_deinit((me_device_t *) me6000_device);
 170                        kfree(me6000_device);
 171                        PERROR("Cannot get memory for subdevice.\n");
 172                        return NULL;
 173                }
 174
 175                me_slist_add_subdevice_tail(&me6000_device->base.slist,
 176                                            subdevice);
 177        }
 178
 179        return (me_device_t *) me6000_device;
 180}
 181
 182// Init and exit of module.
 183
 184static int __init me6000_init(void)
 185{
 186        PDEBUG("executed.\n");
 187
 188        me6000_workqueue = create_singlethread_workqueue("me6000");
 189        return 0;
 190}
 191
 192static void __exit me6000_exit(void)
 193{
 194        PDEBUG("executed.\n");
 195
 196        flush_workqueue(me6000_workqueue);
 197        destroy_workqueue(me6000_workqueue);
 198}
 199
 200module_init(me6000_init);
 201module_exit(me6000_exit);
 202
 203// Administrative stuff for modinfo.
 204MODULE_AUTHOR
 205    ("Guenter Gebhardt <g.gebhardt@meilhaus.de> & Krzysztof Gantzke <k.gantzke@meilhaus.de>");
 206MODULE_DESCRIPTION("Device Driver Module for ME-6000 Device");
 207MODULE_SUPPORTED_DEVICE("Meilhaus ME-6000 Devices");
 208MODULE_LICENSE("GPL");
 209
 210// Export the constructor.
 211EXPORT_SYMBOL(me6000_pci_constructor);
 212
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.