linux/drivers/telephony/ixj_pcmcia.c
<<
>>
Prefs
   1#include "ixj-ver.h"
   2
   3#include <linux/module.h>
   4
   5#include <linux/init.h>
   6#include <linux/kernel.h>       /* printk() */
   7#include <linux/fs.h>           /* everything... */
   8#include <linux/errno.h>        /* error codes */
   9#include <linux/slab.h>
  10
  11#include <pcmcia/cs_types.h>
  12#include <pcmcia/cs.h>
  13#include <pcmcia/cistpl.h>
  14#include <pcmcia/ds.h>
  15
  16#include "ixj.h"
  17
  18/*
  19 *      PCMCIA service support for Quicknet cards
  20 */
  21 
  22#ifdef PCMCIA_DEBUG
  23static int pc_debug = PCMCIA_DEBUG;
  24module_param(pc_debug, int, 0644);
  25#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
  26#else
  27#define DEBUG(n, args...)
  28#endif
  29
  30typedef struct ixj_info_t {
  31        int ndev;
  32        dev_node_t node;
  33        struct ixj *port;
  34} ixj_info_t;
  35
  36static void ixj_detach(struct pcmcia_device *p_dev);
  37static int ixj_config(struct pcmcia_device * link);
  38static void ixj_cs_release(struct pcmcia_device * link);
  39
  40static int ixj_probe(struct pcmcia_device *p_dev)
  41{
  42        DEBUG(0, "ixj_attach()\n");
  43        /* Create new ixj device */
  44        p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
  45        p_dev->io.Attributes2 = IO_DATA_PATH_WIDTH_8;
  46        p_dev->io.IOAddrLines = 3;
  47        p_dev->conf.IntType = INT_MEMORY_AND_IO;
  48        p_dev->priv = kzalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
  49        if (!p_dev->priv) {
  50                return -ENOMEM;
  51        }
  52
  53        return ixj_config(p_dev);
  54}
  55
  56static void ixj_detach(struct pcmcia_device *link)
  57{
  58        DEBUG(0, "ixj_detach(0x%p)\n", link);
  59
  60        ixj_cs_release(link);
  61
  62        kfree(link->priv);
  63}
  64
  65#define CS_CHECK(fn, ret) \
  66do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
  67
  68static void ixj_get_serial(struct pcmcia_device * link, IXJ * j)
  69{
  70        char *str;
  71        int i, place;
  72        DEBUG(0, "ixj_get_serial(0x%p)\n", link);
  73
  74        str = link->prod_id[0];
  75        if (!str)
  76                goto cs_failed;
  77        printk("%s", str);
  78        str = link->prod_id[1];
  79        if (!str)
  80                goto cs_failed;
  81        printk(" %s", str);
  82        str = link->prod_id[2];
  83        if (!str)
  84                goto cs_failed;
  85        place = 1;
  86        for (i = strlen(str) - 1; i >= 0; i--) {
  87                switch (str[i]) {
  88                case '0':
  89                case '1':
  90                case '2':
  91                case '3':
  92                case '4':
  93                case '5':
  94                case '6':
  95                case '7':
  96                case '8':
  97                case '9':
  98                        j->serial += (str[i] - 48) * place;
  99                        break;
 100                case 'A':
 101                case 'B':
 102                case 'C':
 103                case 'D':
 104                case 'E':
 105                case 'F':
 106                        j->serial += (str[i] - 55) * place;
 107                        break;
 108                case 'a':
 109                case 'b':
 110                case 'c':
 111                case 'd':
 112                case 'e':
 113                case 'f':
 114                        j->serial += (str[i] - 87) * place;
 115                        break;
 116                }
 117                place = place * 0x10;
 118        }
 119        str = link->prod_id[3];
 120        if (!str)
 121                goto cs_failed;
 122        printk(" version %s\n", str);
 123      cs_failed:
 124        return;
 125}
 126
 127static int ixj_config_check(struct pcmcia_device *p_dev,
 128                            cistpl_cftable_entry_t *cfg,
 129                            cistpl_cftable_entry_t *dflt,
 130                            unsigned int vcc,
 131                            void *priv_data)
 132{
 133        if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
 134                cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
 135                p_dev->io.BasePort1 = io->win[0].base;
 136                p_dev->io.NumPorts1 = io->win[0].len;
 137                if (io->nwin == 2) {
 138                        p_dev->io.BasePort2 = io->win[1].base;
 139                        p_dev->io.NumPorts2 = io->win[1].len;
 140                }
 141                if (!pcmcia_request_io(p_dev, &p_dev->io))
 142                        return 0;
 143        }
 144        return -ENODEV;
 145}
 146
 147static int ixj_config(struct pcmcia_device * link)
 148{
 149        IXJ *j;
 150        ixj_info_t *info;
 151        cistpl_cftable_entry_t dflt = { 0 };
 152
 153        info = link->priv;
 154        DEBUG(0, "ixj_config(0x%p)\n", link);
 155
 156        if (pcmcia_loop_config(link, ixj_config_check, &dflt))
 157                goto cs_failed;
 158
 159        if (pcmcia_request_configuration(link, &link->conf))
 160                goto cs_failed;
 161
 162        /*
 163         *      Register the card with the core.
 164         */
 165        j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10);
 166
 167        info->ndev = 1;
 168        info->node.major = PHONE_MAJOR;
 169        link->dev_node = &info->node;
 170        ixj_get_serial(link, j);
 171        return 0;
 172
 173      cs_failed:
 174        ixj_cs_release(link);
 175        return -ENODEV;
 176}
 177
 178static void ixj_cs_release(struct pcmcia_device *link)
 179{
 180        ixj_info_t *info = link->priv;
 181        DEBUG(0, "ixj_cs_release(0x%p)\n", link);
 182        info->ndev = 0;
 183        pcmcia_disable_device(link);
 184}
 185
 186static struct pcmcia_device_id ixj_ids[] = {
 187        PCMCIA_DEVICE_MANF_CARD(0x0257, 0x0600),
 188        PCMCIA_DEVICE_NULL
 189};
 190MODULE_DEVICE_TABLE(pcmcia, ixj_ids);
 191
 192static struct pcmcia_driver ixj_driver = {
 193        .owner          = THIS_MODULE,
 194        .drv            = {
 195                .name   = "ixj_cs",
 196        },
 197        .probe          = ixj_probe,
 198        .remove         = ixj_detach,
 199        .id_table       = ixj_ids,
 200};
 201
 202static int __init ixj_pcmcia_init(void)
 203{
 204        return pcmcia_register_driver(&ixj_driver);
 205}
 206
 207static void ixj_pcmcia_exit(void)
 208{
 209        pcmcia_unregister_driver(&ixj_driver);
 210}
 211
 212module_init(ixj_pcmcia_init);
 213module_exit(ixj_pcmcia_exit);
 214
 215MODULE_LICENSE("GPL");
 216