PageRenderTime 109ms CodeModel.GetById 2ms app.highlight 94ms RepoModel.GetById 1ms app.codeStats 1ms

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

https://bitbucket.org/ndreys/linux-sunxi
C | 1172 lines | 1031 code | 88 blank | 53 comment | 67 complexity | acb9205cf78725fb6ed6e7b27e0b672c MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
   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);