linux/drivers/isdn/hisax/sedlbauer_cs.c
<<
>>
Prefs
   1/*======================================================================
   2
   3  A Sedlbauer PCMCIA client driver
   4
   5  This driver is for the Sedlbauer Speed Star and Speed Star II,
   6  which are ISDN PCMCIA Cards.
   7
   8  The contents of this file are subject to the Mozilla Public
   9  License Version 1.1 (the "License"); you may not use this file
  10  except in compliance with the License. You may obtain a copy of
  11  the License at http://www.mozilla.org/MPL/
  12
  13  Software distributed under the License is distributed on an "AS
  14  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  15  implied. See the License for the specific language governing
  16  rights and limitations under the License.
  17
  18  The initial developer of the original code is David A. Hinds
  19  <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  20  are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  21
  22  Modifications from dummy_cs.c are Copyright (C) 1999-2001 Marcus Niemann
  23  <maniemann@users.sourceforge.net>. All Rights Reserved.
  24
  25  Alternatively, the contents of this file may be used under the
  26  terms of the GNU General Public License version 2 (the "GPL"), in
  27  which case the provisions of the GPL are applicable instead of the
  28  above.  If you wish to allow the use of your version of this file
  29  only under the terms of the GPL and not to allow others to use
  30  your version of this file under the MPL, indicate your decision
  31  by deleting the provisions above and replace them with the notice
  32  and other provisions required by the GPL.  If you do not delete
  33  the provisions above, a recipient may use your version of this
  34  file under either the MPL or the GPL.
  35
  36  ======================================================================*/
  37
  38#include <linux/kernel.h>
  39#include <linux/module.h>
  40#include <linux/init.h>
  41#include <linux/ptrace.h>
  42#include <linux/slab.h>
  43#include <linux/string.h>
  44#include <linux/timer.h>
  45#include <linux/ioport.h>
  46#include <asm/io.h>
  47
  48#include <pcmcia/cistpl.h>
  49#include <pcmcia/cisreg.h>
  50#include <pcmcia/ds.h>
  51#include "hisax_cfg.h"
  52
  53MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards");
  54MODULE_AUTHOR("Marcus Niemann");
  55MODULE_LICENSE("Dual MPL/GPL");
  56
  57
  58/*====================================================================*/
  59
  60/* Parameters that can be set with 'insmod' */
  61
  62static int protocol = 2;        /* EURO-ISDN Default */
  63module_param(protocol, int, 0);
  64
  65static int sedlbauer_config(struct pcmcia_device *link);
  66static void sedlbauer_release(struct pcmcia_device *link);
  67
  68static void sedlbauer_detach(struct pcmcia_device *p_dev);
  69
  70typedef struct local_info_t {
  71        struct pcmcia_device    *p_dev;
  72        int                     stop;
  73        int                     cardnr;
  74} local_info_t;
  75
  76static int sedlbauer_probe(struct pcmcia_device *link)
  77{
  78        local_info_t *local;
  79
  80        dev_dbg(&link->dev, "sedlbauer_attach()\n");
  81
  82        /* Allocate space for private device-specific data */
  83        local = kzalloc(sizeof(local_info_t), GFP_KERNEL);
  84        if (!local) return -ENOMEM;
  85        local->cardnr = -1;
  86
  87        local->p_dev = link;
  88        link->priv = local;
  89
  90        return sedlbauer_config(link);
  91} /* sedlbauer_attach */
  92
  93static void sedlbauer_detach(struct pcmcia_device *link)
  94{
  95        dev_dbg(&link->dev, "sedlbauer_detach(0x%p)\n", link);
  96
  97        ((local_info_t *)link->priv)->stop = 1;
  98        sedlbauer_release(link);
  99
 100        /* This points to the parent local_info_t struct */
 101        kfree(link->priv);
 102} /* sedlbauer_detach */
 103
 104static int sedlbauer_config_check(struct pcmcia_device *p_dev, void *priv_data)
 105{
 106        if (p_dev->config_index == 0)
 107                return -EINVAL;
 108
 109        p_dev->io_lines = 3;
 110        return pcmcia_request_io(p_dev);
 111}
 112
 113static int sedlbauer_config(struct pcmcia_device *link)
 114{
 115        int ret;
 116        IsdnCard_t  icard;
 117
 118        dev_dbg(&link->dev, "sedlbauer_config(0x%p)\n", link);
 119
 120        link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_CHECK_VCC |
 121                CONF_AUTO_SET_VPP | CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
 122
 123        ret = pcmcia_loop_config(link, sedlbauer_config_check, NULL);
 124        if (ret)
 125                goto failed;
 126
 127        ret = pcmcia_enable_device(link);
 128        if (ret)
 129                goto failed;
 130
 131        icard.para[0] = link->irq;
 132        icard.para[1] = link->resource[0]->start;
 133        icard.protocol = protocol;
 134        icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA;
 135
 136        ret = hisax_init_pcmcia(link,
 137                                &(((local_info_t *)link->priv)->stop), &icard);
 138        if (ret < 0) {
 139                printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d with %pR\n",
 140                       ret, link->resource[0]);
 141                sedlbauer_release(link);
 142                return -ENODEV;
 143        } else
 144                ((local_info_t *)link->priv)->cardnr = ret;
 145
 146        return 0;
 147
 148failed:
 149        sedlbauer_release(link);
 150        return -ENODEV;
 151
 152} /* sedlbauer_config */
 153
 154static void sedlbauer_release(struct pcmcia_device *link)
 155{
 156        local_info_t *local = link->priv;
 157        dev_dbg(&link->dev, "sedlbauer_release(0x%p)\n", link);
 158
 159        if (local) {
 160                if (local->cardnr >= 0) {
 161                        /* no unregister function with hisax */
 162                        HiSax_closecard(local->cardnr);
 163                }
 164        }
 165
 166        pcmcia_disable_device(link);
 167} /* sedlbauer_release */
 168
 169static int sedlbauer_suspend(struct pcmcia_device *link)
 170{
 171        local_info_t *dev = link->priv;
 172
 173        dev->stop = 1;
 174
 175        return 0;
 176}
 177
 178static int sedlbauer_resume(struct pcmcia_device *link)
 179{
 180        local_info_t *dev = link->priv;
 181
 182        dev->stop = 0;
 183
 184        return 0;
 185}
 186
 187
 188static const struct pcmcia_device_id sedlbauer_ids[] = {
 189        PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "speed star II", "V 3.1", 0x81fb79f5, 0xf3612e1d, 0x6b95c78a),
 190        PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D67", 0x81fb79f5, 0xe4e9bc12, 0x397b7e90),
 191        PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", "4D98", 0x81fb79f5, 0xe4e9bc12, 0x2e5c7fce),
 192        PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (C) 93-94 VK", 0x81fb79f5, 0xe4e9bc12, 0x8db143fe),
 193        PCMCIA_DEVICE_PROD_ID123("SEDLBAUER", "ISDN-Adapter", " (c) 93-95 VK", 0x81fb79f5, 0xe4e9bc12, 0xb391ab4c),
 194        PCMCIA_DEVICE_PROD_ID12("HST High Soft Tech GmbH", "Saphir II B", 0xd79e0b84, 0x21d083ae),
 195/*      PCMCIA_DEVICE_PROD_ID1234("SEDLBAUER", 0x81fb79f5), */ /* too generic*/
 196        PCMCIA_DEVICE_NULL
 197};
 198MODULE_DEVICE_TABLE(pcmcia, sedlbauer_ids);
 199
 200static struct pcmcia_driver sedlbauer_driver = {
 201        .owner          = THIS_MODULE,
 202        .name           = "sedlbauer_cs",
 203        .probe          = sedlbauer_probe,
 204        .remove         = sedlbauer_detach,
 205        .id_table       = sedlbauer_ids,
 206        .suspend        = sedlbauer_suspend,
 207        .resume         = sedlbauer_resume,
 208};
 209module_pcmcia_driver(sedlbauer_driver);
 210