root/drivers/staging/isdn/hysdn/hysdn_init.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hysdn_pci_init_one
  2. hysdn_pci_remove_one
  3. hysdn_init
  4. hysdn_exit

   1 /* $Id: hysdn_init.c,v 1.6.6.6 2001/09/23 22:24:54 kai Exp $
   2  *
   3  * Linux driver for HYSDN cards, init functions.
   4  *
   5  * Author    Werner Cornelius (werner@titro.de) for Hypercope GmbH
   6  * Copyright 1999 by Werner Cornelius (werner@titro.de)
   7  *
   8  * This software may be used and distributed according to the terms
   9  * of the GNU General Public License, incorporated herein by reference.
  10  *
  11  */
  12 
  13 #include <linux/module.h>
  14 #include <linux/init.h>
  15 #include <linux/poll.h>
  16 #include <linux/vmalloc.h>
  17 #include <linux/slab.h>
  18 #include <linux/pci.h>
  19 
  20 #include "hysdn_defs.h"
  21 
  22 static struct pci_device_id hysdn_pci_tbl[] = {
  23         { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
  24           PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO, 0, 0, BD_METRO },
  25         { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
  26           PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, 0, 0, BD_CHAMP2 },
  27         { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
  28           PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, 0, 0, BD_ERGO },
  29         { PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
  30           PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, 0, 0, BD_ERGO },
  31 
  32         { }                             /* Terminating entry */
  33 };
  34 MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl);
  35 MODULE_DESCRIPTION("ISDN4Linux: Driver for HYSDN cards");
  36 MODULE_AUTHOR("Werner Cornelius");
  37 MODULE_LICENSE("GPL");
  38 
  39 static int cardmax;             /* number of found cards */
  40 hysdn_card *card_root = NULL;   /* pointer to first card */
  41 static hysdn_card *card_last = NULL;    /* pointer to first card */
  42 
  43 
  44 /****************************************************************************/
  45 /* The module startup and shutdown code. Only compiled when used as module. */
  46 /* Using the driver as module is always advisable, because the booting      */
  47 /* image becomes smaller and the driver code is only loaded when needed.    */
  48 /* Additionally newer versions may be activated without rebooting.          */
  49 /****************************************************************************/
  50 
  51 /****************************************************************************/
  52 /* init_module is called once when the module is loaded to do all necessary */
  53 /* things like autodetect...                                                */
  54 /* If the return value of this function is 0 the init has been successful   */
  55 /* and the module is added to the list in /proc/modules, otherwise an error */
  56 /* is assumed and the module will not be kept in memory.                    */
  57 /****************************************************************************/
  58 
  59 static int hysdn_pci_init_one(struct pci_dev *akt_pcidev,
  60                               const struct pci_device_id *ent)
  61 {
  62         hysdn_card *card;
  63         int rc;
  64 
  65         rc = pci_enable_device(akt_pcidev);
  66         if (rc)
  67                 return rc;
  68 
  69         if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) {
  70                 printk(KERN_ERR "HYSDN: unable to alloc device mem \n");
  71                 rc = -ENOMEM;
  72                 goto err_out;
  73         }
  74         card->myid = cardmax;   /* set own id */
  75         card->bus = akt_pcidev->bus->number;
  76         card->devfn = akt_pcidev->devfn;        /* slot + function */
  77         card->subsysid = akt_pcidev->subsystem_device;
  78         card->irq = akt_pcidev->irq;
  79         card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE);
  80         card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE);
  81         card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE);
  82         card->brdtype = BD_NONE;        /* unknown */
  83         card->debug_flags = DEF_DEB_FLAGS;      /* set default debug */
  84         card->faxchans = 0;     /* default no fax channels */
  85         card->bchans = 2;       /* and 2 b-channels */
  86         card->brdtype = ent->driver_data;
  87 
  88         if (ergo_inithardware(card)) {
  89                 printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase);
  90                 rc = -EBUSY;
  91                 goto err_out_card;
  92         }
  93 
  94         cardmax++;
  95         card->next = NULL;      /*end of chain */
  96         if (card_last)
  97                 card_last->next = card;         /* pointer to next card */
  98         else
  99                 card_root = card;
 100         card_last = card;       /* new chain end */
 101 
 102         pci_set_drvdata(akt_pcidev, card);
 103         return 0;
 104 
 105 err_out_card:
 106         kfree(card);
 107 err_out:
 108         pci_disable_device(akt_pcidev);
 109         return rc;
 110 }
 111 
 112 static void hysdn_pci_remove_one(struct pci_dev *akt_pcidev)
 113 {
 114         hysdn_card *card = pci_get_drvdata(akt_pcidev);
 115 
 116         pci_set_drvdata(akt_pcidev, NULL);
 117 
 118         if (card->stopcard)
 119                 card->stopcard(card);
 120 
 121 #ifdef CONFIG_HYSDN_CAPI
 122         hycapi_capi_release(card);
 123 #endif
 124 
 125         if (card->releasehardware)
 126                 card->releasehardware(card);   /* free all hardware resources */
 127 
 128         if (card == card_root) {
 129                 card_root = card_root->next;
 130                 if (!card_root)
 131                         card_last = NULL;
 132         } else {
 133                 hysdn_card *tmp = card_root;
 134                 while (tmp) {
 135                         if (tmp->next == card)
 136                                 tmp->next = card->next;
 137                         card_last = tmp;
 138                         tmp = tmp->next;
 139                 }
 140         }
 141 
 142         kfree(card);
 143         pci_disable_device(akt_pcidev);
 144 }
 145 
 146 static struct pci_driver hysdn_pci_driver = {
 147         .name           = "hysdn",
 148         .id_table       = hysdn_pci_tbl,
 149         .probe          = hysdn_pci_init_one,
 150         .remove         = hysdn_pci_remove_one,
 151 };
 152 
 153 static int hysdn_have_procfs;
 154 
 155 static int __init
 156 hysdn_init(void)
 157 {
 158         int rc;
 159 
 160         printk(KERN_NOTICE "HYSDN: module loaded\n");
 161 
 162         rc = pci_register_driver(&hysdn_pci_driver);
 163         if (rc)
 164                 return rc;
 165 
 166         printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax);
 167 
 168         if (!hysdn_procconf_init())
 169                 hysdn_have_procfs = 1;
 170 
 171 #ifdef CONFIG_HYSDN_CAPI
 172         if (cardmax > 0) {
 173                 if (hycapi_init()) {
 174                         printk(KERN_ERR "HYCAPI: init failed\n");
 175 
 176                         if (hysdn_have_procfs)
 177                                 hysdn_procconf_release();
 178 
 179                         pci_unregister_driver(&hysdn_pci_driver);
 180                         return -ESPIPE;
 181                 }
 182         }
 183 #endif /* CONFIG_HYSDN_CAPI */
 184 
 185         return 0;               /* no error */
 186 }                               /* init_module */
 187 
 188 
 189 /***********************************************************************/
 190 /* cleanup_module is called when the module is released by the kernel. */
 191 /* The routine is only called if init_module has been successful and   */
 192 /* the module counter has a value of 0. Otherwise this function will   */
 193 /* not be called. This function must release all resources still allo- */
 194 /* cated as after the return from this function the module code will   */
 195 /* be removed from memory.                                             */
 196 /***********************************************************************/
 197 static void __exit
 198 hysdn_exit(void)
 199 {
 200         if (hysdn_have_procfs)
 201                 hysdn_procconf_release();
 202 
 203         pci_unregister_driver(&hysdn_pci_driver);
 204 
 205 #ifdef CONFIG_HYSDN_CAPI
 206         hycapi_cleanup();
 207 #endif /* CONFIG_HYSDN_CAPI */
 208 
 209         printk(KERN_NOTICE "HYSDN: module unloaded\n");
 210 }                               /* cleanup_module */
 211 
 212 module_init(hysdn_init);
 213 module_exit(hysdn_exit);

/* [<][>][^][v][top][bottom][index][help] */