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