2  * PCMCIA client driver for AVM A1 / Fritz!PCMCIA
 
   5  * Copyright    1998-2001 by Carsten Paeth <calle@calle.in-berlin.de>
 
   7  * This software may be used and distributed according to the terms
 
   8  * of the GNU General Public License, incorporated herein by reference.
 
  12 #include <linux/module.h>
 
  15 #include <linux/kernel.h>
 
  16 #include <linux/init.h>
 
  17 #include <linux/sched.h>
 
  18 #include <linux/ptrace.h>
 
  19 #include <linux/slab.h>
 
  20 #include <linux/string.h>
 
  22 #include <asm/system.h>
 
  24 #include <pcmcia/cs_types.h>
 
  25 #include <pcmcia/cs.h>
 
  26 #include <pcmcia/cistpl.h>
 
  27 #include <pcmcia/ds.h>
 
  28 #include "hisax_cfg.h"
 
  30 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards");
 
  31 MODULE_AUTHOR("Carsten Paeth");
 
  32 MODULE_LICENSE("GPL");
 
  35    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
 
  36    you do not define PCMCIA_DEBUG at all, all the debug code will be
 
  37    left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
 
  38    be present but disabled -- but it can then be enabled for specific
 
  39    modules at load time with a 'pc_debug=#' option to insmod.
 
  42 static int pc_debug = PCMCIA_DEBUG;
 
  43 module_param(pc_debug, int, 0);
 
  44 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
 
  45 static char *version =
 
  46 "avma1_cs.c 1.00 1998/01/23 10:00:00 (Carsten Paeth)";
 
  48 #define DEBUG(n, args...)
 
  51 /*====================================================================*/
 
  53 /* Parameters that can be set with 'insmod' */
 
  55 static int isdnprot = 2;
 
  57 module_param(isdnprot, int, 0);
 
  59 /*====================================================================*/
 
  62    The event() function is this driver's Card Services event handler.
 
  63    It will be called by Card Services when an appropriate card status
 
  64    event is received.  The config() and release() entry points are
 
  65    used to configure or release a socket, in response to card insertion
 
  66    and ejection events.  They are invoked from the skeleton event
 
  70 static void avma1cs_config(dev_link_t *link);
 
  71 static void avma1cs_release(dev_link_t *link);
 
  74    The attach() and detach() entry points are used to create and destroy
 
  75    "instances" of the driver, where each instance represents everything
 
  76    needed to manage one actual PCMCIA card.
 
  79 static void avma1cs_detach(struct pcmcia_device *p_dev);
 
  83    A linked list of "instances" of the skeleton device.  Each actual
 
  84    PCMCIA card corresponds to one device instance, and is described
 
  85    by one dev_link_t structure (defined in ds.h).
 
  87    You may not want to use a linked list for this -- for example, the
 
  88    memory card driver uses an array of dev_link_t pointers, where minor
 
  89    device numbers are used to derive the corresponding array index.
 
  93    A driver needs to provide a dev_node_t structure for each device
 
  94    on a card.  In some cases, there is only one device per card (for
 
  95    example, ethernet cards, modems).  In other cases, there may be
 
  96    many actual or logical devices (SCSI adapters, memory cards with
 
  97    multiple partitions).  The dev_node_t structures need to be kept
 
  98    in a linked list starting at the 'dev' field of a dev_link_t
 
  99    structure.  We allocate them in the card's private data structure,
 
 100    because they generally can't be allocated dynamically.
 
 103 typedef struct local_info_t {
 
 107 /*======================================================================
 
 109     avma1cs_attach() creates an "instance" of the driver, allocating
 
 110     local data structures for one device.  The device is registered
 
 113     The dev_link structure is initialized, but we don't actually
 
 114     configure the card at this point -- we wait until we receive a
 
 115     card insertion event.
 
 117 ======================================================================*/
 
 119 static int avma1cs_attach(struct pcmcia_device *p_dev)
 
 124     DEBUG(0, "avma1cs_attach()\n");
 
 126     /* Initialize the dev_link_t structure */
 
 127     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
 
 130     memset(link, 0, sizeof(struct dev_link_t));
 
 132     /* Allocate space for private device-specific data */
 
 133     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
 
 138     memset(local, 0, sizeof(local_info_t));
 
 141     /* The io structure describes IO port mapping */
 
 142     link->io.NumPorts1 = 16;
 
 143     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
 
 144     link->io.NumPorts2 = 16;
 
 145     link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
 
 146     link->io.IOAddrLines = 5;
 
 148     /* Interrupt setup */
 
 149     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
 
 150     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
 
 152     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
 
 154     /* General socket configuration */
 
 155     link->conf.Attributes = CONF_ENABLE_IRQ;
 
 157     link->conf.IntType = INT_MEMORY_AND_IO;
 
 158     link->conf.ConfigIndex = 1;
 
 159     link->conf.Present = PRESENT_OPTION;
 
 161     link->handle = p_dev;
 
 162     p_dev->instance = link;
 
 164     link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
 
 165     avma1cs_config(link);
 
 168 } /* avma1cs_attach */
 
 170 /*======================================================================
 
 172     This deletes a driver "instance".  The device is de-registered
 
 173     with Card Services.  If it has been released, all local data
 
 174     structures are freed.  Otherwise, the structures will be freed
 
 175     when the device is released.
 
 177 ======================================================================*/
 
 179 static void avma1cs_detach(struct pcmcia_device *p_dev)
 
 181     dev_link_t *link = dev_to_instance(p_dev);
 
 183     DEBUG(0, "avma1cs_detach(0x%p)\n", link);
 
 185     if (link->state & DEV_CONFIG)
 
 186             avma1cs_release(link);
 
 190 } /* avma1cs_detach */
 
 192 /*======================================================================
 
 194     avma1cs_config() is scheduled to run after a CARD_INSERTION event
 
 195     is received, to configure the PCMCIA socket, and to make the
 
 196     ethernet device available to the system.
 
 198 ======================================================================*/
 
 200 static int get_tuple(client_handle_t handle, tuple_t *tuple,
 
 203     int i = pcmcia_get_tuple_data(handle, tuple);
 
 204     if (i != CS_SUCCESS) return i;
 
 205     return pcmcia_parse_tuple(handle, tuple, parse);
 
 208 static int first_tuple(client_handle_t handle, tuple_t *tuple,
 
 211     int i = pcmcia_get_first_tuple(handle, tuple);
 
 212     if (i != CS_SUCCESS) return i;
 
 213     return get_tuple(handle, tuple, parse);
 
 216 static int next_tuple(client_handle_t handle, tuple_t *tuple,
 
 219     int i = pcmcia_get_next_tuple(handle, tuple);
 
 220     if (i != CS_SUCCESS) return i;
 
 221     return get_tuple(handle, tuple, parse);
 
 224 static void avma1cs_config(dev_link_t *link)
 
 226     client_handle_t handle;
 
 229     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
 
 237     handle = link->handle;
 
 240     DEBUG(0, "avma1cs_config(0x%p)\n", link);
 
 243        This reads the card's CONFIG tuple to find its configuration
 
 247         tuple.DesiredTuple = CISTPL_CONFIG;
 
 248         i = pcmcia_get_first_tuple(handle, &tuple);
 
 249         if (i != CS_SUCCESS) break;
 
 250         tuple.TupleData = buf;
 
 251         tuple.TupleDataMax = 64;
 
 252         tuple.TupleOffset = 0;
 
 253         i = pcmcia_get_tuple_data(handle, &tuple);
 
 254         if (i != CS_SUCCESS) break;
 
 255         i = pcmcia_parse_tuple(handle, &tuple, &parse);
 
 256         if (i != CS_SUCCESS) break;
 
 257         link->conf.ConfigBase = parse.config.base;
 
 259     if (i != CS_SUCCESS) {
 
 260         cs_error(link->handle, ParseTuple, i);
 
 261         link->state &= ~DEV_CONFIG_PENDING;
 
 266     link->state |= DEV_CONFIG;
 
 270         tuple.Attributes = 0;
 
 271         tuple.TupleData = buf;
 
 272         tuple.TupleDataMax = 254;
 
 273         tuple.TupleOffset = 0;
 
 274         tuple.DesiredTuple = CISTPL_VERS_1;
 
 277         if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
 
 278             strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
 
 284         tuple.TupleData = (cisdata_t *)buf;
 
 285         tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
 
 286         tuple.Attributes = 0;
 
 287         tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
 
 288         i = first_tuple(handle, &tuple, &parse);
 
 289         while (i == CS_SUCCESS) {
 
 290             if (cf->io.nwin > 0) {
 
 291                 link->conf.ConfigIndex = cf->index;
 
 292                 link->io.BasePort1 = cf->io.win[0].base;
 
 293                 link->io.NumPorts1 = cf->io.win[0].len;
 
 294                 link->io.NumPorts2 = 0;
 
 295                 printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
 
 297                         link->io.BasePort1+link->io.NumPorts1 - 1);
 
 298                 i = pcmcia_request_io(link->handle, &link->io);
 
 299                 if (i == CS_SUCCESS) goto found_port;
 
 301             i = next_tuple(handle, &tuple, &parse);
 
 305         if (i != CS_SUCCESS) {
 
 306             cs_error(link->handle, RequestIO, i);
 
 311          * allocate an interrupt line
 
 313         i = pcmcia_request_irq(link->handle, &link->irq);
 
 314         if (i != CS_SUCCESS) {
 
 315             cs_error(link->handle, RequestIRQ, i);
 
 316             pcmcia_release_io(link->handle, &link->io);
 
 321          * configure the PCMCIA socket
 
 323         i = pcmcia_request_configuration(link->handle, &link->conf);
 
 324         if (i != CS_SUCCESS) {
 
 325             cs_error(link->handle, RequestConfiguration, i);
 
 326             pcmcia_release_io(link->handle, &link->io);
 
 327             pcmcia_release_irq(link->handle, &link->irq);
 
 333     /* At this point, the dev_node_t structure(s) should be
 
 334        initialized and arranged in a linked list at link->dev. */
 
 336     strcpy(dev->node.dev_name, "A1");
 
 337     dev->node.major = 45;
 
 339     link->dev = &dev->node;
 
 341     link->state &= ~DEV_CONFIG_PENDING;
 
 342     /* If any step failed, release any partially configured state */
 
 344         avma1cs_release(link);
 
 348     printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
 
 349                                 link->io.BasePort1, link->irq.AssignedIRQ);
 
 351     icard.para[0] = link->irq.AssignedIRQ;
 
 352     icard.para[1] = link->io.BasePort1;
 
 353     icard.protocol = isdnprot;
 
 354     icard.typ = ISDN_CTYPE_A1_PCMCIA;
 
 356     i = hisax_init_pcmcia(link, &busy, &icard);
 
 358         printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
 
 359         avma1cs_release(link);
 
 364 } /* avma1cs_config */
 
 366 /*======================================================================
 
 368     After a card is removed, avma1cs_release() will unregister the net
 
 369     device, and release the PCMCIA configuration.  If the device is
 
 370     still open, this will be postponed until it is closed.
 
 372 ======================================================================*/
 
 374 static void avma1cs_release(dev_link_t *link)
 
 376     local_info_t *local = link->priv;
 
 378     DEBUG(0, "avma1cs_release(0x%p)\n", link);
 
 380     /* no unregister function with hisax */
 
 381     HiSax_closecard(local->node.minor);
 
 383     /* Unlink the device chain */
 
 386     /* Don't bother checking to see if these succeed or not */
 
 387     pcmcia_release_configuration(link->handle);
 
 388     pcmcia_release_io(link->handle, &link->io);
 
 389     pcmcia_release_irq(link->handle, &link->irq);
 
 390     link->state &= ~DEV_CONFIG;
 
 391 } /* avma1cs_release */
 
 393 static int avma1cs_suspend(struct pcmcia_device *dev)
 
 395         dev_link_t *link = dev_to_instance(dev);
 
 397         link->state |= DEV_SUSPEND;
 
 398         if (link->state & DEV_CONFIG)
 
 399                 pcmcia_release_configuration(link->handle);
 
 404 static int avma1cs_resume(struct pcmcia_device *dev)
 
 406         dev_link_t *link = dev_to_instance(dev);
 
 408         link->state &= ~DEV_SUSPEND;
 
 409         if (link->state & DEV_CONFIG)
 
 410                 pcmcia_request_configuration(link->handle, &link->conf);
 
 416 static struct pcmcia_device_id avma1cs_ids[] = {
 
 417         PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
 
 418         PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b),
 
 421 MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids);
 
 423 static struct pcmcia_driver avma1cs_driver = {
 
 424         .owner          = THIS_MODULE,
 
 428         .probe          = avma1cs_attach,
 
 429         .remove         = avma1cs_detach,
 
 430         .id_table       = avma1cs_ids,
 
 431         .suspend        = avma1cs_suspend,
 
 432         .resume         = avma1cs_resume,
 
 435 /*====================================================================*/
 
 437 static int __init init_avma1_cs(void)
 
 439         return(pcmcia_register_driver(&avma1cs_driver));
 
 442 static void __exit exit_avma1_cs(void)
 
 444         pcmcia_unregister_driver(&avma1cs_driver);
 
 447 module_init(init_avma1_cs);
 
 448 module_exit(exit_avma1_cs);