root/drivers/isdn/hardware/mISDN/mISDNinfineon.c

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

DEFINITIONS

This source file includes following definitions.
  1. _set_debug
  2. set_debug
  3. IOFUNC_IO
  4. diva20x_irq
  5. tiger_irq
  6. elsa_irq
  7. niccy_irq
  8. gazel_irq
  9. ipac_irq
  10. enable_hwirq
  11. disable_hwirq
  12. ipac_chip_reset
  13. reset_inf
  14. inf_ctrl
  15. init_irq
  16. release_io
  17. setup_io
  18. release_card
  19. setup_instance
  20. get_card_info
  21. inf_probe
  22. inf_remove
  23. infineon_init
  24. infineon_cleanup

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * mISDNinfineon.c
   4  *              Support for cards based on following Infineon ISDN chipsets
   5  *              - ISAC + HSCX
   6  *              - IPAC and IPAC-X
   7  *              - ISAC-SX + HSCX
   8  *
   9  * Supported cards:
  10  *              - Dialogic Diva 2.0
  11  *              - Dialogic Diva 2.0U
  12  *              - Dialogic Diva 2.01
  13  *              - Dialogic Diva 2.02
  14  *              - Sedlbauer Speedwin
  15  *              - HST Saphir3
  16  *              - Develo (former ELSA) Microlink PCI (Quickstep 1000)
  17  *              - Develo (former ELSA) Quickstep 3000
  18  *              - Berkom Scitel BRIX Quadro
  19  *              - Dr.Neuhaus (Sagem) Niccy
  20  *
  21  * Author       Karsten Keil <keil@isdn4linux.de>
  22  *
  23  * Copyright 2009  by Karsten Keil <keil@isdn4linux.de>
  24  */
  25 
  26 #include <linux/interrupt.h>
  27 #include <linux/module.h>
  28 #include <linux/pci.h>
  29 #include <linux/delay.h>
  30 #include <linux/mISDNhw.h>
  31 #include <linux/slab.h>
  32 #include "ipac.h"
  33 
  34 #define INFINEON_REV    "1.0"
  35 
  36 static int inf_cnt;
  37 static u32 debug;
  38 static u32 irqloops = 4;
  39 
  40 enum inf_types {
  41         INF_NONE,
  42         INF_DIVA20,
  43         INF_DIVA20U,
  44         INF_DIVA201,
  45         INF_DIVA202,
  46         INF_SPEEDWIN,
  47         INF_SAPHIR3,
  48         INF_QS1000,
  49         INF_QS3000,
  50         INF_NICCY,
  51         INF_SCT_1,
  52         INF_SCT_2,
  53         INF_SCT_3,
  54         INF_SCT_4,
  55         INF_GAZEL_R685,
  56         INF_GAZEL_R753
  57 };
  58 
  59 enum addr_mode {
  60         AM_NONE = 0,
  61         AM_IO,
  62         AM_MEMIO,
  63         AM_IND_IO,
  64 };
  65 
  66 struct inf_cinfo {
  67         enum inf_types  typ;
  68         const char      *full;
  69         const char      *name;
  70         enum addr_mode  cfg_mode;
  71         enum addr_mode  addr_mode;
  72         u8              cfg_bar;
  73         u8              addr_bar;
  74         void            *irqfunc;
  75 };
  76 
  77 struct _ioaddr {
  78         enum addr_mode  mode;
  79         union {
  80                 void __iomem    *p;
  81                 struct _ioport  io;
  82         } a;
  83 };
  84 
  85 struct _iohandle {
  86         enum addr_mode  mode;
  87         resource_size_t size;
  88         resource_size_t start;
  89         void __iomem    *p;
  90 };
  91 
  92 struct inf_hw {
  93         struct list_head        list;
  94         struct pci_dev          *pdev;
  95         const struct inf_cinfo  *ci;
  96         char                    name[MISDN_MAX_IDLEN];
  97         u32                     irq;
  98         u32                     irqcnt;
  99         struct _iohandle        cfg;
 100         struct _iohandle        addr;
 101         struct _ioaddr          isac;
 102         struct _ioaddr          hscx;
 103         spinlock_t              lock;   /* HW access lock */
 104         struct ipac_hw          ipac;
 105         struct inf_hw           *sc[3]; /* slave cards */
 106 };
 107 
 108 
 109 #define PCI_SUBVENDOR_HST_SAPHIR3       0x52
 110 #define PCI_SUBVENDOR_SEDLBAUER_PCI     0x53
 111 #define PCI_SUB_ID_SEDLBAUER            0x01
 112 
 113 static struct pci_device_id infineon_ids[] = {
 114         { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20), INF_DIVA20 },
 115         { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20_U), INF_DIVA20U },
 116         { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA201), INF_DIVA201 },
 117         { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA202), INF_DIVA202 },
 118         { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
 119           PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0,
 120           INF_SPEEDWIN },
 121         { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100,
 122           PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3 },
 123         { PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_MICROLINK), INF_QS1000 },
 124         { PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_QS3000), INF_QS3000 },
 125         { PCI_VDEVICE(SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY), INF_NICCY },
 126         { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
 127           PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0,
 128           INF_SCT_1 },
 129         { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R685), INF_GAZEL_R685 },
 130         { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R753), INF_GAZEL_R753 },
 131         { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO), INF_GAZEL_R753 },
 132         { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_OLITEC), INF_GAZEL_R753 },
 133         { }
 134 };
 135 MODULE_DEVICE_TABLE(pci, infineon_ids);
 136 
 137 /* PCI interface specific defines */
 138 /* Diva 2.0/2.0U */
 139 #define DIVA_HSCX_PORT          0x00
 140 #define DIVA_HSCX_ALE           0x04
 141 #define DIVA_ISAC_PORT          0x08
 142 #define DIVA_ISAC_ALE           0x0C
 143 #define DIVA_PCI_CTRL           0x10
 144 
 145 /* DIVA_PCI_CTRL bits */
 146 #define DIVA_IRQ_BIT            0x01
 147 #define DIVA_RESET_BIT          0x08
 148 #define DIVA_EEPROM_CLK         0x40
 149 #define DIVA_LED_A              0x10
 150 #define DIVA_LED_B              0x20
 151 #define DIVA_IRQ_CLR            0x80
 152 
 153 /* Diva 2.01/2.02 */
 154 /* Siemens PITA */
 155 #define PITA_ICR_REG            0x00
 156 #define PITA_INT0_STATUS        0x02
 157 
 158 #define PITA_MISC_REG           0x1c
 159 #define PITA_PARA_SOFTRESET     0x01000000
 160 #define PITA_SER_SOFTRESET      0x02000000
 161 #define PITA_PARA_MPX_MODE      0x04000000
 162 #define PITA_INT0_ENABLE        0x00020000
 163 
 164 /* TIGER 100 Registers */
 165 #define TIGER_RESET_ADDR        0x00
 166 #define TIGER_EXTERN_RESET      0x01
 167 #define TIGER_AUX_CTRL          0x02
 168 #define TIGER_AUX_DATA          0x03
 169 #define TIGER_AUX_IRQMASK       0x05
 170 #define TIGER_AUX_STATUS        0x07
 171 
 172 /* Tiger AUX BITs */
 173 #define TIGER_IOMASK            0xdd    /* 1 and 5 are inputs */
 174 #define TIGER_IRQ_BIT           0x02
 175 
 176 #define TIGER_IPAC_ALE          0xC0
 177 #define TIGER_IPAC_PORT         0xC8
 178 
 179 /* ELSA (now Develo) PCI cards */
 180 #define ELSA_IRQ_ADDR           0x4c
 181 #define ELSA_IRQ_MASK           0x04
 182 #define QS1000_IRQ_OFF          0x01
 183 #define QS3000_IRQ_OFF          0x03
 184 #define QS1000_IRQ_ON           0x41
 185 #define QS3000_IRQ_ON           0x43
 186 
 187 /* Dr Neuhaus/Sagem Niccy */
 188 #define NICCY_ISAC_PORT         0x00
 189 #define NICCY_HSCX_PORT         0x01
 190 #define NICCY_ISAC_ALE          0x02
 191 #define NICCY_HSCX_ALE          0x03
 192 
 193 #define NICCY_IRQ_CTRL_REG      0x38
 194 #define NICCY_IRQ_ENABLE        0x001f00
 195 #define NICCY_IRQ_DISABLE       0xff0000
 196 #define NICCY_IRQ_BIT           0x800000
 197 
 198 
 199 /* Scitel PLX */
 200 #define SCT_PLX_IRQ_ADDR        0x4c
 201 #define SCT_PLX_RESET_ADDR      0x50
 202 #define SCT_PLX_IRQ_ENABLE      0x41
 203 #define SCT_PLX_RESET_BIT       0x04
 204 
 205 /* Gazel */
 206 #define GAZEL_IPAC_DATA_PORT    0x04
 207 /* Gazel PLX */
 208 #define GAZEL_CNTRL             0x50
 209 #define GAZEL_RESET             0x04
 210 #define GAZEL_RESET_9050        0x40000000
 211 #define GAZEL_INCSR             0x4C
 212 #define GAZEL_ISAC_EN           0x08
 213 #define GAZEL_INT_ISAC          0x20
 214 #define GAZEL_HSCX_EN           0x01
 215 #define GAZEL_INT_HSCX          0x04
 216 #define GAZEL_PCI_EN            0x40
 217 #define GAZEL_IPAC_EN           0x03
 218 
 219 
 220 static LIST_HEAD(Cards);
 221 static DEFINE_RWLOCK(card_lock); /* protect Cards */
 222 
 223 static void
 224 _set_debug(struct inf_hw *card)
 225 {
 226         card->ipac.isac.dch.debug = debug;
 227         card->ipac.hscx[0].bch.debug = debug;
 228         card->ipac.hscx[1].bch.debug = debug;
 229 }
 230 
 231 static int
 232 set_debug(const char *val, const struct kernel_param *kp)
 233 {
 234         int ret;
 235         struct inf_hw *card;
 236 
 237         ret = param_set_uint(val, kp);
 238         if (!ret) {
 239                 read_lock(&card_lock);
 240                 list_for_each_entry(card, &Cards, list)
 241                         _set_debug(card);
 242                 read_unlock(&card_lock);
 243         }
 244         return ret;
 245 }
 246 
 247 MODULE_AUTHOR("Karsten Keil");
 248 MODULE_LICENSE("GPL v2");
 249 MODULE_VERSION(INFINEON_REV);
 250 module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
 251 MODULE_PARM_DESC(debug, "infineon debug mask");
 252 module_param(irqloops, uint, S_IRUGO | S_IWUSR);
 253 MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)");
 254 
 255 /* Interface functions */
 256 
 257 IOFUNC_IO(ISAC, inf_hw, isac.a.io)
 258 IOFUNC_IO(IPAC, inf_hw, hscx.a.io)
 259 IOFUNC_IND(ISAC, inf_hw, isac.a.io)
 260 IOFUNC_IND(IPAC, inf_hw, hscx.a.io)
 261 IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p)
 262 IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p)
 263 
 264 static irqreturn_t
 265 diva_irq(int intno, void *dev_id)
 266 {
 267         struct inf_hw *hw = dev_id;
 268         u8 val;
 269 
 270         spin_lock(&hw->lock);
 271         val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL);
 272         if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */
 273                 spin_unlock(&hw->lock);
 274                 return IRQ_NONE; /* shared */
 275         }
 276         hw->irqcnt++;
 277         mISDNipac_irq(&hw->ipac, irqloops);
 278         spin_unlock(&hw->lock);
 279         return IRQ_HANDLED;
 280 }
 281 
 282 static irqreturn_t
 283 diva20x_irq(int intno, void *dev_id)
 284 {
 285         struct inf_hw *hw = dev_id;
 286         u8 val;
 287 
 288         spin_lock(&hw->lock);
 289         val = readb(hw->cfg.p);
 290         if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */
 291                 spin_unlock(&hw->lock);
 292                 return IRQ_NONE; /* shared */
 293         }
 294         hw->irqcnt++;
 295         mISDNipac_irq(&hw->ipac, irqloops);
 296         writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */
 297         spin_unlock(&hw->lock);
 298         return IRQ_HANDLED;
 299 }
 300 
 301 static irqreturn_t
 302 tiger_irq(int intno, void *dev_id)
 303 {
 304         struct inf_hw *hw = dev_id;
 305         u8 val;
 306 
 307         spin_lock(&hw->lock);
 308         val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS);
 309         if (val & TIGER_IRQ_BIT) { /* for us or shared ? */
 310                 spin_unlock(&hw->lock);
 311                 return IRQ_NONE; /* shared */
 312         }
 313         hw->irqcnt++;
 314         mISDNipac_irq(&hw->ipac, irqloops);
 315         spin_unlock(&hw->lock);
 316         return IRQ_HANDLED;
 317 }
 318 
 319 static irqreturn_t
 320 elsa_irq(int intno, void *dev_id)
 321 {
 322         struct inf_hw *hw = dev_id;
 323         u8 val;
 324 
 325         spin_lock(&hw->lock);
 326         val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR);
 327         if (!(val & ELSA_IRQ_MASK)) {
 328                 spin_unlock(&hw->lock);
 329                 return IRQ_NONE; /* shared */
 330         }
 331         hw->irqcnt++;
 332         mISDNipac_irq(&hw->ipac, irqloops);
 333         spin_unlock(&hw->lock);
 334         return IRQ_HANDLED;
 335 }
 336 
 337 static irqreturn_t
 338 niccy_irq(int intno, void *dev_id)
 339 {
 340         struct inf_hw *hw = dev_id;
 341         u32 val;
 342 
 343         spin_lock(&hw->lock);
 344         val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 345         if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */
 346                 spin_unlock(&hw->lock);
 347                 return IRQ_NONE; /* shared */
 348         }
 349         outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 350         hw->irqcnt++;
 351         mISDNipac_irq(&hw->ipac, irqloops);
 352         spin_unlock(&hw->lock);
 353         return IRQ_HANDLED;
 354 }
 355 
 356 static irqreturn_t
 357 gazel_irq(int intno, void *dev_id)
 358 {
 359         struct inf_hw *hw = dev_id;
 360         irqreturn_t ret;
 361 
 362         spin_lock(&hw->lock);
 363         ret = mISDNipac_irq(&hw->ipac, irqloops);
 364         spin_unlock(&hw->lock);
 365         return ret;
 366 }
 367 
 368 static irqreturn_t
 369 ipac_irq(int intno, void *dev_id)
 370 {
 371         struct inf_hw *hw = dev_id;
 372         u8 val;
 373 
 374         spin_lock(&hw->lock);
 375         val = hw->ipac.read_reg(hw, IPAC_ISTA);
 376         if (!(val & 0x3f)) {
 377                 spin_unlock(&hw->lock);
 378                 return IRQ_NONE; /* shared */
 379         }
 380         hw->irqcnt++;
 381         mISDNipac_irq(&hw->ipac, irqloops);
 382         spin_unlock(&hw->lock);
 383         return IRQ_HANDLED;
 384 }
 385 
 386 static void
 387 enable_hwirq(struct inf_hw *hw)
 388 {
 389         u16 w;
 390         u32 val;
 391 
 392         switch (hw->ci->typ) {
 393         case INF_DIVA201:
 394         case INF_DIVA202:
 395                 writel(PITA_INT0_ENABLE, hw->cfg.p);
 396                 break;
 397         case INF_SPEEDWIN:
 398         case INF_SAPHIR3:
 399                 outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
 400                 break;
 401         case INF_QS1000:
 402                 outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 403                 break;
 404         case INF_QS3000:
 405                 outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 406                 break;
 407         case INF_NICCY:
 408                 val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 409                 val |= NICCY_IRQ_ENABLE;
 410                 outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 411                 break;
 412         case INF_SCT_1:
 413                 w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 414                 w |= SCT_PLX_IRQ_ENABLE;
 415                 outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 416                 break;
 417         case INF_GAZEL_R685:
 418                 outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN,
 419                      (u32)hw->cfg.start + GAZEL_INCSR);
 420                 break;
 421         case INF_GAZEL_R753:
 422                 outb(GAZEL_IPAC_EN + GAZEL_PCI_EN,
 423                      (u32)hw->cfg.start + GAZEL_INCSR);
 424                 break;
 425         default:
 426                 break;
 427         }
 428 }
 429 
 430 static void
 431 disable_hwirq(struct inf_hw *hw)
 432 {
 433         u16 w;
 434         u32 val;
 435 
 436         switch (hw->ci->typ) {
 437         case INF_DIVA201:
 438         case INF_DIVA202:
 439                 writel(0, hw->cfg.p);
 440                 break;
 441         case INF_SPEEDWIN:
 442         case INF_SAPHIR3:
 443                 outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK);
 444                 break;
 445         case INF_QS1000:
 446                 outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 447                 break;
 448         case INF_QS3000:
 449                 outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR);
 450                 break;
 451         case INF_NICCY:
 452                 val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 453                 val &= NICCY_IRQ_DISABLE;
 454                 outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG);
 455                 break;
 456         case INF_SCT_1:
 457                 w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 458                 w &= (~SCT_PLX_IRQ_ENABLE);
 459                 outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR);
 460                 break;
 461         case INF_GAZEL_R685:
 462         case INF_GAZEL_R753:
 463                 outb(0, (u32)hw->cfg.start + GAZEL_INCSR);
 464                 break;
 465         default:
 466                 break;
 467         }
 468 }
 469 
 470 static void
 471 ipac_chip_reset(struct inf_hw *hw)
 472 {
 473         hw->ipac.write_reg(hw, IPAC_POTA2, 0x20);
 474         mdelay(5);
 475         hw->ipac.write_reg(hw, IPAC_POTA2, 0x00);
 476         mdelay(5);
 477         hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf);
 478         hw->ipac.write_reg(hw, IPAC_MASK, 0xc0);
 479 }
 480 
 481 static void
 482 reset_inf(struct inf_hw *hw)
 483 {
 484         u16 w;
 485         u32 val;
 486 
 487         if (debug & DEBUG_HW)
 488                 pr_notice("%s: resetting card\n", hw->name);
 489         switch (hw->ci->typ) {
 490         case INF_DIVA20:
 491         case INF_DIVA20U:
 492                 outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL);
 493                 mdelay(10);
 494                 outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL);
 495                 mdelay(10);
 496                 /* Workaround PCI9060 */
 497                 outb(9, (u32)hw->cfg.start + 0x69);
 498                 outb(DIVA_RESET_BIT | DIVA_LED_A,
 499                      (u32)hw->cfg.start + DIVA_PCI_CTRL);
 500                 break;
 501         case INF_DIVA201:
 502                 writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
 503                        hw->cfg.p + PITA_MISC_REG);
 504                 mdelay(1);
 505                 writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG);
 506                 mdelay(10);
 507                 break;
 508         case INF_DIVA202:
 509                 writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE,
 510                        hw->cfg.p + PITA_MISC_REG);
 511                 mdelay(1);
 512                 writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET,
 513                        hw->cfg.p + PITA_MISC_REG);
 514                 mdelay(10);
 515                 break;
 516         case INF_SPEEDWIN:
 517         case INF_SAPHIR3:
 518                 ipac_chip_reset(hw);
 519                 hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
 520                 hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
 521                 hw->ipac.write_reg(hw, IPAC_PCFG, 0x12);
 522                 break;
 523         case INF_QS1000:
 524         case INF_QS3000:
 525                 ipac_chip_reset(hw);
 526                 hw->ipac.write_reg(hw, IPAC_ACFG, 0x00);
 527                 hw->ipac.write_reg(hw, IPAC_AOE, 0x3c);
 528                 hw->ipac.write_reg(hw, IPAC_ATX, 0xff);
 529                 break;
 530         case INF_NICCY:
 531                 break;
 532         case INF_SCT_1:
 533                 w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 534                 w &= (~SCT_PLX_RESET_BIT);
 535                 outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 536                 mdelay(10);
 537                 w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 538                 w |= SCT_PLX_RESET_BIT;
 539                 outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR);
 540                 mdelay(10);
 541                 break;
 542         case INF_GAZEL_R685:
 543                 val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
 544                 val |= (GAZEL_RESET_9050 + GAZEL_RESET);
 545                 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 546                 val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
 547                 mdelay(4);
 548                 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 549                 mdelay(10);
 550                 hw->ipac.isac.adf2 = 0x87;
 551                 hw->ipac.hscx[0].slot = 0x1f;
 552                 hw->ipac.hscx[1].slot = 0x23;
 553                 break;
 554         case INF_GAZEL_R753:
 555                 val = inl((u32)hw->cfg.start + GAZEL_CNTRL);
 556                 val |= (GAZEL_RESET_9050 + GAZEL_RESET);
 557                 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 558                 val &= ~(GAZEL_RESET_9050 + GAZEL_RESET);
 559                 mdelay(4);
 560                 outl(val, (u32)hw->cfg.start + GAZEL_CNTRL);
 561                 mdelay(10);
 562                 ipac_chip_reset(hw);
 563                 hw->ipac.write_reg(hw, IPAC_ACFG, 0xff);
 564                 hw->ipac.write_reg(hw, IPAC_AOE, 0x00);
 565                 hw->ipac.conf = 0x01; /* IOM off */
 566                 break;
 567         default:
 568                 return;
 569         }
 570         enable_hwirq(hw);
 571 }
 572 
 573 static int
 574 inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg)
 575 {
 576         int ret = 0;
 577 
 578         switch (cmd) {
 579         case HW_RESET_REQ:
 580                 reset_inf(hw);
 581                 break;
 582         default:
 583                 pr_info("%s: %s unknown command %x %lx\n",
 584                         hw->name, __func__, cmd, arg);
 585                 ret = -EINVAL;
 586                 break;
 587         }
 588         return ret;
 589 }
 590 
 591 static int
 592 init_irq(struct inf_hw *hw)
 593 {
 594         int     ret, cnt = 3;
 595         u_long  flags;
 596 
 597         if (!hw->ci->irqfunc)
 598                 return -EINVAL;
 599         ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw);
 600         if (ret) {
 601                 pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq);
 602                 return ret;
 603         }
 604         while (cnt--) {
 605                 spin_lock_irqsave(&hw->lock, flags);
 606                 reset_inf(hw);
 607                 ret = hw->ipac.init(&hw->ipac);
 608                 if (ret) {
 609                         spin_unlock_irqrestore(&hw->lock, flags);
 610                         pr_info("%s: ISAC init failed with %d\n",
 611                                 hw->name, ret);
 612                         break;
 613                 }
 614                 spin_unlock_irqrestore(&hw->lock, flags);
 615                 msleep_interruptible(10);
 616                 if (debug & DEBUG_HW)
 617                         pr_notice("%s: IRQ %d count %d\n", hw->name,
 618                                   hw->irq, hw->irqcnt);
 619                 if (!hw->irqcnt) {
 620                         pr_info("%s: IRQ(%d) got no requests during init %d\n",
 621                                 hw->name, hw->irq, 3 - cnt);
 622                 } else
 623                         return 0;
 624         }
 625         free_irq(hw->irq, hw);
 626         return -EIO;
 627 }
 628 
 629 static void
 630 release_io(struct inf_hw *hw)
 631 {
 632         if (hw->cfg.mode) {
 633                 if (hw->cfg.p) {
 634                         release_mem_region(hw->cfg.start, hw->cfg.size);
 635                         iounmap(hw->cfg.p);
 636                 } else
 637                         release_region(hw->cfg.start, hw->cfg.size);
 638                 hw->cfg.mode = AM_NONE;
 639         }
 640         if (hw->addr.mode) {
 641                 if (hw->addr.p) {
 642                         release_mem_region(hw->addr.start, hw->addr.size);
 643                         iounmap(hw->addr.p);
 644                 } else
 645                         release_region(hw->addr.start, hw->addr.size);
 646                 hw->addr.mode = AM_NONE;
 647         }
 648 }
 649 
 650 static int
 651 setup_io(struct inf_hw *hw)
 652 {
 653         int err = 0;
 654 
 655         if (hw->ci->cfg_mode) {
 656                 hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar);
 657                 hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar);
 658                 if (hw->ci->cfg_mode == AM_MEMIO) {
 659                         if (!request_mem_region(hw->cfg.start, hw->cfg.size,
 660                                                 hw->name))
 661                                 err = -EBUSY;
 662                 } else {
 663                         if (!request_region(hw->cfg.start, hw->cfg.size,
 664                                             hw->name))
 665                                 err = -EBUSY;
 666                 }
 667                 if (err) {
 668                         pr_info("mISDN: %s config port %lx (%lu bytes)"
 669                                 "already in use\n", hw->name,
 670                                 (ulong)hw->cfg.start, (ulong)hw->cfg.size);
 671                         return err;
 672                 }
 673                 if (hw->ci->cfg_mode == AM_MEMIO)
 674                         hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
 675                 hw->cfg.mode = hw->ci->cfg_mode;
 676                 if (debug & DEBUG_HW)
 677                         pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
 678                                   hw->name, (ulong)hw->cfg.start,
 679                                   (ulong)hw->cfg.size, hw->ci->cfg_mode);
 680 
 681         }
 682         if (hw->ci->addr_mode) {
 683                 hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar);
 684                 hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar);
 685                 if (hw->ci->addr_mode == AM_MEMIO) {
 686                         if (!request_mem_region(hw->addr.start, hw->addr.size,
 687                                                 hw->name))
 688                                 err = -EBUSY;
 689                 } else {
 690                         if (!request_region(hw->addr.start, hw->addr.size,
 691                                             hw->name))
 692                                 err = -EBUSY;
 693                 }
 694                 if (err) {
 695                         pr_info("mISDN: %s address port %lx (%lu bytes)"
 696                                 "already in use\n", hw->name,
 697                                 (ulong)hw->addr.start, (ulong)hw->addr.size);
 698                         return err;
 699                 }
 700                 if (hw->ci->addr_mode == AM_MEMIO) {
 701                         hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
 702                         if (unlikely(!hw->addr.p))
 703                                 return -ENOMEM;
 704                 }
 705                 hw->addr.mode = hw->ci->addr_mode;
 706                 if (debug & DEBUG_HW)
 707                         pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
 708                                   hw->name, (ulong)hw->addr.start,
 709                                   (ulong)hw->addr.size, hw->ci->addr_mode);
 710 
 711         }
 712 
 713         switch (hw->ci->typ) {
 714         case INF_DIVA20:
 715         case INF_DIVA20U:
 716                 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
 717                 hw->isac.mode = hw->cfg.mode;
 718                 hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE;
 719                 hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT;
 720                 hw->hscx.mode = hw->cfg.mode;
 721                 hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE;
 722                 hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT;
 723                 break;
 724         case INF_DIVA201:
 725                 hw->ipac.type = IPAC_TYPE_IPAC;
 726                 hw->ipac.isac.off = 0x80;
 727                 hw->isac.mode = hw->addr.mode;
 728                 hw->isac.a.p = hw->addr.p;
 729                 hw->hscx.mode = hw->addr.mode;
 730                 hw->hscx.a.p = hw->addr.p;
 731                 break;
 732         case INF_DIVA202:
 733                 hw->ipac.type = IPAC_TYPE_IPACX;
 734                 hw->isac.mode = hw->addr.mode;
 735                 hw->isac.a.p = hw->addr.p;
 736                 hw->hscx.mode = hw->addr.mode;
 737                 hw->hscx.a.p = hw->addr.p;
 738                 break;
 739         case INF_SPEEDWIN:
 740         case INF_SAPHIR3:
 741                 hw->ipac.type = IPAC_TYPE_IPAC;
 742                 hw->ipac.isac.off = 0x80;
 743                 hw->isac.mode = hw->cfg.mode;
 744                 hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
 745                 hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
 746                 hw->hscx.mode = hw->cfg.mode;
 747                 hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE;
 748                 hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT;
 749                 outb(0xff, (ulong)hw->cfg.start);
 750                 mdelay(1);
 751                 outb(0x00, (ulong)hw->cfg.start);
 752                 mdelay(1);
 753                 outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL);
 754                 break;
 755         case INF_QS1000:
 756         case INF_QS3000:
 757                 hw->ipac.type = IPAC_TYPE_IPAC;
 758                 hw->ipac.isac.off = 0x80;
 759                 hw->isac.a.io.ale = (u32)hw->addr.start;
 760                 hw->isac.a.io.port = (u32)hw->addr.start + 1;
 761                 hw->isac.mode = hw->addr.mode;
 762                 hw->hscx.a.io.ale = (u32)hw->addr.start;
 763                 hw->hscx.a.io.port = (u32)hw->addr.start + 1;
 764                 hw->hscx.mode = hw->addr.mode;
 765                 break;
 766         case INF_NICCY:
 767                 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
 768                 hw->isac.mode = hw->addr.mode;
 769                 hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE;
 770                 hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT;
 771                 hw->hscx.mode = hw->addr.mode;
 772                 hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE;
 773                 hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT;
 774                 break;
 775         case INF_SCT_1:
 776                 hw->ipac.type = IPAC_TYPE_IPAC;
 777                 hw->ipac.isac.off = 0x80;
 778                 hw->isac.a.io.ale = (u32)hw->addr.start;
 779                 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 780                 hw->isac.mode = hw->addr.mode;
 781                 hw->hscx.a.io.ale = hw->isac.a.io.ale;
 782                 hw->hscx.a.io.port = hw->isac.a.io.port;
 783                 hw->hscx.mode = hw->addr.mode;
 784                 break;
 785         case INF_SCT_2:
 786                 hw->ipac.type = IPAC_TYPE_IPAC;
 787                 hw->ipac.isac.off = 0x80;
 788                 hw->isac.a.io.ale = (u32)hw->addr.start + 0x08;
 789                 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 790                 hw->isac.mode = hw->addr.mode;
 791                 hw->hscx.a.io.ale = hw->isac.a.io.ale;
 792                 hw->hscx.a.io.port = hw->isac.a.io.port;
 793                 hw->hscx.mode = hw->addr.mode;
 794                 break;
 795         case INF_SCT_3:
 796                 hw->ipac.type = IPAC_TYPE_IPAC;
 797                 hw->ipac.isac.off = 0x80;
 798                 hw->isac.a.io.ale = (u32)hw->addr.start + 0x10;
 799                 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 800                 hw->isac.mode = hw->addr.mode;
 801                 hw->hscx.a.io.ale = hw->isac.a.io.ale;
 802                 hw->hscx.a.io.port = hw->isac.a.io.port;
 803                 hw->hscx.mode = hw->addr.mode;
 804                 break;
 805         case INF_SCT_4:
 806                 hw->ipac.type = IPAC_TYPE_IPAC;
 807                 hw->ipac.isac.off = 0x80;
 808                 hw->isac.a.io.ale = (u32)hw->addr.start + 0x20;
 809                 hw->isac.a.io.port = hw->isac.a.io.ale + 4;
 810                 hw->isac.mode = hw->addr.mode;
 811                 hw->hscx.a.io.ale = hw->isac.a.io.ale;
 812                 hw->hscx.a.io.port = hw->isac.a.io.port;
 813                 hw->hscx.mode = hw->addr.mode;
 814                 break;
 815         case INF_GAZEL_R685:
 816                 hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX;
 817                 hw->ipac.isac.off = 0x80;
 818                 hw->isac.mode = hw->addr.mode;
 819                 hw->isac.a.io.port = (u32)hw->addr.start;
 820                 hw->hscx.mode = hw->addr.mode;
 821                 hw->hscx.a.io.port = hw->isac.a.io.port;
 822                 break;
 823         case INF_GAZEL_R753:
 824                 hw->ipac.type = IPAC_TYPE_IPAC;
 825                 hw->ipac.isac.off = 0x80;
 826                 hw->isac.mode = hw->addr.mode;
 827                 hw->isac.a.io.ale = (u32)hw->addr.start;
 828                 hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT;
 829                 hw->hscx.mode = hw->addr.mode;
 830                 hw->hscx.a.io.ale = hw->isac.a.io.ale;
 831                 hw->hscx.a.io.port = hw->isac.a.io.port;
 832                 break;
 833         default:
 834                 return -EINVAL;
 835         }
 836         switch (hw->isac.mode) {
 837         case AM_MEMIO:
 838                 ASSIGN_FUNC_IPAC(MIO, hw->ipac);
 839                 break;
 840         case AM_IND_IO:
 841                 ASSIGN_FUNC_IPAC(IND, hw->ipac);
 842                 break;
 843         case AM_IO:
 844                 ASSIGN_FUNC_IPAC(IO, hw->ipac);
 845                 break;
 846         default:
 847                 return -EINVAL;
 848         }
 849         return 0;
 850 }
 851 
 852 static void
 853 release_card(struct inf_hw *card) {
 854         ulong   flags;
 855         int     i;
 856 
 857         spin_lock_irqsave(&card->lock, flags);
 858         disable_hwirq(card);
 859         spin_unlock_irqrestore(&card->lock, flags);
 860         card->ipac.isac.release(&card->ipac.isac);
 861         free_irq(card->irq, card);
 862         mISDN_unregister_device(&card->ipac.isac.dch.dev);
 863         release_io(card);
 864         write_lock_irqsave(&card_lock, flags);
 865         list_del(&card->list);
 866         write_unlock_irqrestore(&card_lock, flags);
 867         switch (card->ci->typ) {
 868         case INF_SCT_2:
 869         case INF_SCT_3:
 870         case INF_SCT_4:
 871                 break;
 872         case INF_SCT_1:
 873                 for (i = 0; i < 3; i++) {
 874                         if (card->sc[i])
 875                                 release_card(card->sc[i]);
 876                         card->sc[i] = NULL;
 877                 }
 878                 /* fall through */
 879         default:
 880                 pci_disable_device(card->pdev);
 881                 pci_set_drvdata(card->pdev, NULL);
 882                 break;
 883         }
 884         kfree(card);
 885         inf_cnt--;
 886 }
 887 
 888 static int
 889 setup_instance(struct inf_hw *card)
 890 {
 891         int err;
 892         ulong flags;
 893 
 894         snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name,
 895                  inf_cnt + 1);
 896         write_lock_irqsave(&card_lock, flags);
 897         list_add_tail(&card->list, &Cards);
 898         write_unlock_irqrestore(&card_lock, flags);
 899 
 900         _set_debug(card);
 901         card->ipac.isac.name = card->name;
 902         card->ipac.name = card->name;
 903         card->ipac.owner = THIS_MODULE;
 904         spin_lock_init(&card->lock);
 905         card->ipac.isac.hwlock = &card->lock;
 906         card->ipac.hwlock = &card->lock;
 907         card->ipac.ctrl = (void *)&inf_ctrl;
 908 
 909         err = setup_io(card);
 910         if (err)
 911                 goto error_setup;
 912 
 913         card->ipac.isac.dch.dev.Bprotocols =
 914                 mISDNipac_init(&card->ipac, card);
 915 
 916         if (card->ipac.isac.dch.dev.Bprotocols == 0)
 917                 goto error_setup;
 918 
 919         err = mISDN_register_device(&card->ipac.isac.dch.dev,
 920                                     &card->pdev->dev, card->name);
 921         if (err)
 922                 goto error;
 923 
 924         err = init_irq(card);
 925         if (!err)  {
 926                 inf_cnt++;
 927                 pr_notice("Infineon %d cards installed\n", inf_cnt);
 928                 return 0;
 929         }
 930         mISDN_unregister_device(&card->ipac.isac.dch.dev);
 931 error:
 932         card->ipac.release(&card->ipac);
 933 error_setup:
 934         release_io(card);
 935         write_lock_irqsave(&card_lock, flags);
 936         list_del(&card->list);
 937         write_unlock_irqrestore(&card_lock, flags);
 938         return err;
 939 }
 940 
 941 static const struct inf_cinfo inf_card_info[] = {
 942         {
 943                 INF_DIVA20,
 944                 "Dialogic Diva 2.0",
 945                 "diva20",
 946                 AM_IND_IO, AM_NONE, 2, 0,
 947                 &diva_irq
 948         },
 949         {
 950                 INF_DIVA20U,
 951                 "Dialogic Diva 2.0U",
 952                 "diva20U",
 953                 AM_IND_IO, AM_NONE, 2, 0,
 954                 &diva_irq
 955         },
 956         {
 957                 INF_DIVA201,
 958                 "Dialogic Diva 2.01",
 959                 "diva201",
 960                 AM_MEMIO, AM_MEMIO, 0, 1,
 961                 &diva20x_irq
 962         },
 963         {
 964                 INF_DIVA202,
 965                 "Dialogic Diva 2.02",
 966                 "diva202",
 967                 AM_MEMIO, AM_MEMIO, 0, 1,
 968                 &diva20x_irq
 969         },
 970         {
 971                 INF_SPEEDWIN,
 972                 "Sedlbauer SpeedWin PCI",
 973                 "speedwin",
 974                 AM_IND_IO, AM_NONE, 0, 0,
 975                 &tiger_irq
 976         },
 977         {
 978                 INF_SAPHIR3,
 979                 "HST Saphir 3",
 980                 "saphir",
 981                 AM_IND_IO, AM_NONE, 0, 0,
 982                 &tiger_irq
 983         },
 984         {
 985                 INF_QS1000,
 986                 "Develo Microlink PCI",
 987                 "qs1000",
 988                 AM_IO, AM_IND_IO, 1, 3,
 989                 &elsa_irq
 990         },
 991         {
 992                 INF_QS3000,
 993                 "Develo QuickStep 3000",
 994                 "qs3000",
 995                 AM_IO, AM_IND_IO, 1, 3,
 996                 &elsa_irq
 997         },
 998         {
 999                 INF_NICCY,
1000                 "Sagem NICCY",
1001                 "niccy",
1002                 AM_IO, AM_IND_IO, 0, 1,
1003                 &niccy_irq
1004         },
1005         {
1006                 INF_SCT_1,
1007                 "SciTel Quadro",
1008                 "p1_scitel",
1009                 AM_IO, AM_IND_IO, 1, 5,
1010                 &ipac_irq
1011         },
1012         {
1013                 INF_SCT_2,
1014                 "SciTel Quadro",
1015                 "p2_scitel",
1016                 AM_NONE, AM_IND_IO, 0, 4,
1017                 &ipac_irq
1018         },
1019         {
1020                 INF_SCT_3,
1021                 "SciTel Quadro",
1022                 "p3_scitel",
1023                 AM_NONE, AM_IND_IO, 0, 3,
1024                 &ipac_irq
1025         },
1026         {
1027                 INF_SCT_4,
1028                 "SciTel Quadro",
1029                 "p4_scitel",
1030                 AM_NONE, AM_IND_IO, 0, 2,
1031                 &ipac_irq
1032         },
1033         {
1034                 INF_GAZEL_R685,
1035                 "Gazel R685",
1036                 "gazel685",
1037                 AM_IO, AM_IO, 1, 2,
1038                 &gazel_irq
1039         },
1040         {
1041                 INF_GAZEL_R753,
1042                 "Gazel R753",
1043                 "gazel753",
1044                 AM_IO, AM_IND_IO, 1, 2,
1045                 &ipac_irq
1046         },
1047         {
1048                 INF_NONE,
1049         }
1050 };
1051 
1052 static const struct inf_cinfo *
1053 get_card_info(enum inf_types typ)
1054 {
1055         const struct inf_cinfo *ci = inf_card_info;
1056 
1057         while (ci->typ != INF_NONE) {
1058                 if (ci->typ == typ)
1059                         return ci;
1060                 ci++;
1061         }
1062         return NULL;
1063 }
1064 
1065 static int
1066 inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1067 {
1068         int err = -ENOMEM;
1069         struct inf_hw *card;
1070 
1071         card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1072         if (!card) {
1073                 pr_info("No memory for Infineon ISDN card\n");
1074                 return err;
1075         }
1076         card->pdev = pdev;
1077         err = pci_enable_device(pdev);
1078         if (err) {
1079                 kfree(card);
1080                 return err;
1081         }
1082         card->ci = get_card_info(ent->driver_data);
1083         if (!card->ci) {
1084                 pr_info("mISDN: do not have information about adapter at %s\n",
1085                         pci_name(pdev));
1086                 kfree(card);
1087                 pci_disable_device(pdev);
1088                 return -EINVAL;
1089         } else
1090                 pr_notice("mISDN: found adapter %s at %s\n",
1091                           card->ci->full, pci_name(pdev));
1092 
1093         card->irq = pdev->irq;
1094         pci_set_drvdata(pdev, card);
1095         err = setup_instance(card);
1096         if (err) {
1097                 pci_disable_device(pdev);
1098                 kfree(card);
1099                 pci_set_drvdata(pdev, NULL);
1100         } else if (ent->driver_data == INF_SCT_1) {
1101                 int i;
1102                 struct inf_hw *sc;
1103 
1104                 for (i = 1; i < 4; i++) {
1105                         sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL);
1106                         if (!sc) {
1107                                 release_card(card);
1108                                 pci_disable_device(pdev);
1109                                 return -ENOMEM;
1110                         }
1111                         sc->irq = card->irq;
1112                         sc->pdev = card->pdev;
1113                         sc->ci = card->ci + i;
1114                         err = setup_instance(sc);
1115                         if (err) {
1116                                 pci_disable_device(pdev);
1117                                 kfree(sc);
1118                                 release_card(card);
1119                                 break;
1120                         } else
1121                                 card->sc[i - 1] = sc;
1122                 }
1123         }
1124         return err;
1125 }
1126 
1127 static void
1128 inf_remove(struct pci_dev *pdev)
1129 {
1130         struct inf_hw   *card = pci_get_drvdata(pdev);
1131 
1132         if (card)
1133                 release_card(card);
1134         else
1135                 pr_debug("%s: drvdata already removed\n", __func__);
1136 }
1137 
1138 static struct pci_driver infineon_driver = {
1139         .name = "ISDN Infineon pci",
1140         .probe = inf_probe,
1141         .remove = inf_remove,
1142         .id_table = infineon_ids,
1143 };
1144 
1145 static int __init
1146 infineon_init(void)
1147 {
1148         int err;
1149 
1150         pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV);
1151         err = pci_register_driver(&infineon_driver);
1152         return err;
1153 }
1154 
1155 static void __exit
1156 infineon_cleanup(void)
1157 {
1158         pci_unregister_driver(&infineon_driver);
1159 }
1160 
1161 module_init(infineon_init);
1162 module_exit(infineon_cleanup);

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