cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mISDNinfineon.c (27241B)


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