linux/drivers/isdn/hardware/avm/b1pci.c
<<
>>
Prefs
   1/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $
   2 * 
   3 * Module for AVM B1 PCI-card.
   4 * 
   5 * Copyright 1999 by Carsten Paeth <calle@calle.de>
   6 * 
   7 * This software may be used and distributed according to the terms
   8 * of the GNU General Public License, incorporated herein by reference.
   9 *
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/kernel.h>
  14#include <linux/skbuff.h>
  15#include <linux/delay.h>
  16#include <linux/mm.h>
  17#include <linux/interrupt.h>
  18#include <linux/ioport.h>
  19#include <linux/pci.h>
  20#include <linux/capi.h>
  21#include <asm/io.h>
  22#include <linux/init.h>
  23#include <linux/isdn/capicmd.h>
  24#include <linux/isdn/capiutil.h>
  25#include <linux/isdn/capilli.h>
  26#include "avmcard.h"
  27
  28/* ------------------------------------------------------------- */
  29
  30static char *revision = "$Revision: 1.1.2.2 $";
  31
  32/* ------------------------------------------------------------- */
  33
  34static struct pci_device_id b1pci_pci_tbl[] = {
  35        { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
  36        { }                             /* Terminating entry */
  37};
  38
  39MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
  40MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card");
  41MODULE_AUTHOR("Carsten Paeth");
  42MODULE_LICENSE("GPL");
  43
  44/* ------------------------------------------------------------- */
  45
  46static char *b1pci_procinfo(struct capi_ctr *ctrl)
  47{
  48        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
  49
  50        if (!cinfo)
  51                return "";
  52        sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
  53                cinfo->cardname[0] ? cinfo->cardname : "-",
  54                cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
  55                cinfo->card ? cinfo->card->port : 0x0,
  56                cinfo->card ? cinfo->card->irq : 0,
  57                cinfo->card ? cinfo->card->revision : 0
  58                );
  59        return cinfo->infobuf;
  60}
  61
  62/* ------------------------------------------------------------- */
  63
  64static int b1pci_probe(struct capicardparams *p, struct pci_dev *pdev)
  65{
  66        avmcard *card;
  67        avmctrl_info *cinfo;
  68        int retval;
  69
  70        card = b1_alloc_card(1);
  71        if (!card) {
  72                printk(KERN_WARNING "b1pci: no memory.\n");
  73                retval = -ENOMEM;
  74                goto err;
  75        }
  76
  77        cinfo = card->ctrlinfo;
  78        sprintf(card->name, "b1pci-%x", p->port);
  79        card->port = p->port;
  80        card->irq = p->irq;
  81        card->cardtype = avm_b1pci;
  82        
  83        if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
  84                printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n",
  85                       card->port, card->port + AVMB1_PORTLEN);
  86                retval = -EBUSY;
  87                goto err_free;
  88        }
  89        b1_reset(card->port);
  90        retval = b1_detect(card->port, card->cardtype);
  91        if (retval) {
  92                printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
  93                       card->port, retval);
  94                retval = -ENODEV;
  95                goto err_release_region;
  96        }
  97        b1_reset(card->port);
  98        b1_getrevision(card);
  99        
 100        retval = request_irq(card->irq, b1_interrupt, IRQF_SHARED, card->name, card);
 101        if (retval) {
 102                printk(KERN_ERR "b1pci: unable to get IRQ %d.\n", card->irq);
 103                retval = -EBUSY;
 104                goto err_release_region;
 105        }
 106        
 107        cinfo->capi_ctrl.driver_name   = "b1pci";
 108        cinfo->capi_ctrl.driverdata    = cinfo;
 109        cinfo->capi_ctrl.register_appl = b1_register_appl;
 110        cinfo->capi_ctrl.release_appl  = b1_release_appl;
 111        cinfo->capi_ctrl.send_message  = b1_send_message;
 112        cinfo->capi_ctrl.load_firmware = b1_load_firmware;
 113        cinfo->capi_ctrl.reset_ctr     = b1_reset_ctr;
 114        cinfo->capi_ctrl.procinfo      = b1pci_procinfo;
 115        cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc;
 116        strcpy(cinfo->capi_ctrl.name, card->name);
 117        cinfo->capi_ctrl.owner         = THIS_MODULE;
 118
 119        retval = attach_capi_ctr(&cinfo->capi_ctrl);
 120        if (retval) {
 121                printk(KERN_ERR "b1pci: attach controller failed.\n");
 122                goto err_free_irq;
 123        }
 124
 125        if (card->revision >= 4) {
 126                printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n",
 127                       card->port, card->irq, card->revision);
 128        } else {
 129                printk(KERN_INFO "b1pci: AVM B1 PCI at i/o %#x, irq %d, revision %d\n",
 130                       card->port, card->irq, card->revision);
 131        }
 132
 133        pci_set_drvdata(pdev, card);
 134        return 0;
 135
 136 err_free_irq:
 137        free_irq(card->irq, card);
 138 err_release_region:
 139        release_region(card->port, AVMB1_PORTLEN);
 140 err_free:
 141        b1_free_card(card);
 142 err:
 143        return retval;
 144}
 145
 146static void b1pci_remove(struct pci_dev *pdev)
 147{
 148        avmcard *card = pci_get_drvdata(pdev);
 149        avmctrl_info *cinfo = card->ctrlinfo;
 150        unsigned int port = card->port;
 151
 152        b1_reset(port);
 153        b1_reset(port);
 154
 155        detach_capi_ctr(&cinfo->capi_ctrl);
 156        free_irq(card->irq, card);
 157        release_region(card->port, AVMB1_PORTLEN);
 158        b1_free_card(card);
 159}
 160
 161#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 162/* ------------------------------------------------------------- */
 163
 164static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
 165{
 166        avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 167
 168        if (!cinfo)
 169                return "";
 170        sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx r%d",
 171                cinfo->cardname[0] ? cinfo->cardname : "-",
 172                cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
 173                cinfo->card ? cinfo->card->port : 0x0,
 174                cinfo->card ? cinfo->card->irq : 0,
 175                cinfo->card ? cinfo->card->membase : 0,
 176                cinfo->card ? cinfo->card->revision : 0
 177                );
 178        return cinfo->infobuf;
 179}
 180
 181/* ------------------------------------------------------------- */
 182
 183static int b1pciv4_probe(struct capicardparams *p, struct pci_dev *pdev)
 184{
 185        avmcard *card;
 186        avmctrl_info *cinfo;
 187        int retval;
 188
 189        card = b1_alloc_card(1);
 190        if (!card) {
 191                printk(KERN_WARNING "b1pci: no memory.\n");
 192                retval = -ENOMEM;
 193                goto err;
 194        }
 195
 196        card->dma = avmcard_dma_alloc("b1pci", pdev, 2048+128, 2048+128);
 197        if (!card->dma) {
 198                printk(KERN_WARNING "b1pci: dma alloc.\n");
 199                retval = -ENOMEM;
 200                goto err_free;
 201        }
 202
 203        cinfo = card->ctrlinfo;
 204        sprintf(card->name, "b1pciv4-%x", p->port);
 205        card->port = p->port;
 206        card->irq = p->irq;
 207        card->membase = p->membase;
 208        card->cardtype = avm_b1pci;
 209
 210        if (!request_region(card->port, AVMB1_PORTLEN, card->name)) {
 211                printk(KERN_WARNING "b1pci: ports 0x%03x-0x%03x in use.\n",
 212                       card->port, card->port + AVMB1_PORTLEN);
 213                retval = -EBUSY;
 214                goto err_free_dma;
 215        }
 216
 217        card->mbase = ioremap(card->membase, 64);
 218        if (!card->mbase) {
 219                printk(KERN_NOTICE "b1pci: can't remap memory at 0x%lx\n",
 220                       card->membase);
 221                retval = -ENOMEM;
 222                goto err_release_region;
 223        }
 224
 225        b1dma_reset(card);
 226
 227        retval = b1pciv4_detect(card);
 228        if (retval) {
 229                printk(KERN_NOTICE "b1pci: NO card at 0x%x (%d)\n",
 230                       card->port, retval);
 231                retval = -ENODEV;
 232                goto err_unmap;
 233        }
 234        b1dma_reset(card);
 235        b1_getrevision(card);
 236
 237        retval = request_irq(card->irq, b1dma_interrupt, IRQF_SHARED, card->name, card);
 238        if (retval) {
 239                printk(KERN_ERR "b1pci: unable to get IRQ %d.\n",
 240                       card->irq);
 241                retval = -EBUSY;
 242                goto err_unmap;
 243        }
 244
 245        cinfo->capi_ctrl.owner         = THIS_MODULE;
 246        cinfo->capi_ctrl.driver_name   = "b1pciv4";
 247        cinfo->capi_ctrl.driverdata    = cinfo;
 248        cinfo->capi_ctrl.register_appl = b1dma_register_appl;
 249        cinfo->capi_ctrl.release_appl  = b1dma_release_appl;
 250        cinfo->capi_ctrl.send_message  = b1dma_send_message;
 251        cinfo->capi_ctrl.load_firmware = b1dma_load_firmware;
 252        cinfo->capi_ctrl.reset_ctr     = b1dma_reset_ctr;
 253        cinfo->capi_ctrl.procinfo      = b1pciv4_procinfo;
 254        cinfo->capi_ctrl.ctr_read_proc = b1dmactl_read_proc;
 255        strcpy(cinfo->capi_ctrl.name, card->name);
 256
 257        retval = attach_capi_ctr(&cinfo->capi_ctrl);
 258        if (retval) {
 259                printk(KERN_ERR "b1pci: attach controller failed.\n");
 260                goto err_free_irq;
 261        }
 262        card->cardnr = cinfo->capi_ctrl.cnr;
 263
 264        printk(KERN_INFO "b1pci: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
 265               card->port, card->irq, card->membase, card->revision);
 266
 267        pci_set_drvdata(pdev, card);
 268        return 0;
 269
 270 err_free_irq:
 271        free_irq(card->irq, card);
 272 err_unmap:
 273        iounmap(card->mbase);
 274 err_release_region:
 275        release_region(card->port, AVMB1_PORTLEN);
 276 err_free_dma:
 277        avmcard_dma_free(card->dma);
 278 err_free:
 279        b1_free_card(card);
 280 err:
 281        return retval;
 282
 283}
 284
 285static void b1pciv4_remove(struct pci_dev *pdev)
 286{
 287        avmcard *card = pci_get_drvdata(pdev);
 288        avmctrl_info *cinfo = card->ctrlinfo;
 289
 290        b1dma_reset(card);
 291
 292        detach_capi_ctr(&cinfo->capi_ctrl);
 293        free_irq(card->irq, card);
 294        iounmap(card->mbase);
 295        release_region(card->port, AVMB1_PORTLEN);
 296        avmcard_dma_free(card->dma);
 297        b1_free_card(card);
 298}
 299
 300#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
 301
 302static int __devinit b1pci_pci_probe(struct pci_dev *pdev,
 303                                     const struct pci_device_id *ent)
 304{
 305        struct capicardparams param;
 306        int retval;
 307
 308        if (pci_enable_device(pdev) < 0) {
 309                printk(KERN_ERR "b1pci: failed to enable AVM-B1\n");
 310                return -ENODEV;
 311        }
 312        param.irq = pdev->irq;
 313
 314        if (pci_resource_start(pdev, 2)) { /* B1 PCI V4 */
 315#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 316                pci_set_master(pdev);
 317#endif
 318                param.membase = pci_resource_start(pdev, 0);
 319                param.port = pci_resource_start(pdev, 2);
 320
 321                printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
 322                       param.port, param.irq, param.membase);
 323#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 324                retval = b1pciv4_probe(&param, pdev);
 325#else
 326                retval = b1pci_probe(&param, pdev);
 327#endif
 328                if (retval != 0) {
 329                        printk(KERN_ERR "b1pci: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n",
 330                               param.port, param.irq, param.membase);
 331                }
 332        } else {
 333                param.membase = 0;
 334                param.port = pci_resource_start(pdev, 1);
 335
 336                printk(KERN_INFO "b1pci: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
 337                       param.port, param.irq);
 338                retval = b1pci_probe(&param, pdev);
 339                if (retval != 0) {
 340                        printk(KERN_ERR "b1pci: no AVM-B1 at i/o %#x, irq %d detected\n",
 341                               param.port, param.irq);
 342                }
 343        }
 344        return retval;
 345}
 346
 347static void __devexit b1pci_pci_remove(struct pci_dev *pdev)
 348{
 349#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 350        avmcard *card = pci_get_drvdata(pdev);
 351
 352        if (card->dma)
 353                b1pciv4_remove(pdev);
 354        else
 355                b1pci_remove(pdev);
 356#else
 357        b1pci_remove(pdev);
 358#endif
 359}
 360
 361static struct pci_driver b1pci_pci_driver = {
 362        .name           = "b1pci",
 363        .id_table       = b1pci_pci_tbl,
 364        .probe          = b1pci_pci_probe,
 365        .remove         = __devexit_p(b1pci_pci_remove),
 366};
 367
 368static struct capi_driver capi_driver_b1pci = {
 369        .name           = "b1pci",
 370        .revision       = "1.0",
 371};
 372#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 373static struct capi_driver capi_driver_b1pciv4 = {
 374        .name           = "b1pciv4",
 375        .revision       = "1.0",
 376};
 377#endif
 378
 379static int __init b1pci_init(void)
 380{
 381        char *p;
 382        char rev[32];
 383        int err;
 384
 385        if ((p = strchr(revision, ':')) != NULL && p[1]) {
 386                strlcpy(rev, p + 2, 32);
 387                if ((p = strchr(rev, '$')) != NULL && p > rev)
 388                   *(p-1) = 0;
 389        } else
 390                strcpy(rev, "1.0");
 391
 392
 393        err = pci_register_driver(&b1pci_pci_driver);
 394        if (!err) {
 395                strlcpy(capi_driver_b1pci.revision, rev, 32);
 396                register_capi_driver(&capi_driver_b1pci);
 397#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 398                strlcpy(capi_driver_b1pciv4.revision, rev, 32);
 399                register_capi_driver(&capi_driver_b1pciv4);
 400#endif
 401                printk(KERN_INFO "b1pci: revision %s\n", rev);
 402        }
 403        return err;
 404}
 405
 406static void __exit b1pci_exit(void)
 407{
 408        unregister_capi_driver(&capi_driver_b1pci);
 409#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
 410        unregister_capi_driver(&capi_driver_b1pciv4);
 411#endif
 412        pci_unregister_driver(&b1pci_pci_driver);
 413}
 414
 415module_init(b1pci_init);
 416module_exit(b1pci_exit);
 417