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