diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/isdn/hardware/mISDN/mISDNinfineon.c')
-rw-r--r-- | ANDROID_3.4.5/drivers/isdn/hardware/mISDN/mISDNinfineon.c | 1173 |
1 files changed, 0 insertions, 1173 deletions
diff --git a/ANDROID_3.4.5/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/ANDROID_3.4.5/drivers/isdn/hardware/mISDN/mISDNinfineon.c deleted file mode 100644 index 631eb3fa..00000000 --- a/ANDROID_3.4.5/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ /dev/null @@ -1,1173 +0,0 @@ -/* - * mISDNinfineon.c - * Support for cards based on following Infineon ISDN chipsets - * - ISAC + HSCX - * - IPAC and IPAC-X - * - ISAC-SX + HSCX - * - * Supported cards: - * - Dialogic Diva 2.0 - * - Dialogic Diva 2.0U - * - Dialogic Diva 2.01 - * - Dialogic Diva 2.02 - * - Sedlbauer Speedwin - * - HST Saphir3 - * - Develo (former ELSA) Microlink PCI (Quickstep 1000) - * - Develo (former ELSA) Quickstep 3000 - * - Berkom Scitel BRIX Quadro - * - Dr.Neuhaus (Sagem) Niccy - * - * - * - * Author Karsten Keil <keil@isdn4linux.de> - * - * Copyright 2009 by Karsten Keil <keil@isdn4linux.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/mISDNhw.h> -#include <linux/slab.h> -#include "ipac.h" - -#define INFINEON_REV "1.0" - -static int inf_cnt; -static u32 debug; -static u32 irqloops = 4; - -enum inf_types { - INF_NONE, - INF_DIVA20, - INF_DIVA20U, - INF_DIVA201, - INF_DIVA202, - INF_SPEEDWIN, - INF_SAPHIR3, - INF_QS1000, - INF_QS3000, - INF_NICCY, - INF_SCT_1, - INF_SCT_2, - INF_SCT_3, - INF_SCT_4, - INF_GAZEL_R685, - INF_GAZEL_R753 -}; - -enum addr_mode { - AM_NONE = 0, - AM_IO, - AM_MEMIO, - AM_IND_IO, -}; - -struct inf_cinfo { - enum inf_types typ; - const char *full; - const char *name; - enum addr_mode cfg_mode; - enum addr_mode addr_mode; - u8 cfg_bar; - u8 addr_bar; - void *irqfunc; -}; - -struct _ioaddr { - enum addr_mode mode; - union { - void __iomem *p; - struct _ioport io; - } a; -}; - -struct _iohandle { - enum addr_mode mode; - resource_size_t size; - resource_size_t start; - void __iomem *p; -}; - -struct inf_hw { - struct list_head list; - struct pci_dev *pdev; - const struct inf_cinfo *ci; - char name[MISDN_MAX_IDLEN]; - u32 irq; - u32 irqcnt; - struct _iohandle cfg; - struct _iohandle addr; - struct _ioaddr isac; - struct _ioaddr hscx; - spinlock_t lock; /* HW access lock */ - struct ipac_hw ipac; - struct inf_hw *sc[3]; /* slave cards */ -}; - - -#define PCI_SUBVENDOR_HST_SAPHIR3 0x52 -#define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53 -#define PCI_SUB_ID_SEDLBAUER 0x01 - -static struct pci_device_id infineon_ids[] __devinitdata = { - { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20), INF_DIVA20 }, - { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA20_U), INF_DIVA20U }, - { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA201), INF_DIVA201 }, - { PCI_VDEVICE(EICON, PCI_DEVICE_ID_EICON_DIVA202), INF_DIVA202 }, - { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, - PCI_SUBVENDOR_SEDLBAUER_PCI, PCI_SUB_ID_SEDLBAUER, 0, 0, - INF_SPEEDWIN }, - { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, - PCI_SUBVENDOR_HST_SAPHIR3, PCI_SUB_ID_SEDLBAUER, 0, 0, INF_SAPHIR3 }, - { PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_MICROLINK), INF_QS1000 }, - { PCI_VDEVICE(ELSA, PCI_DEVICE_ID_ELSA_QS3000), INF_QS3000 }, - { PCI_VDEVICE(SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY), INF_NICCY }, - { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, - PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO, 0, 0, - INF_SCT_1 }, - { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R685), INF_GAZEL_R685 }, - { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_R753), INF_GAZEL_R753 }, - { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO), INF_GAZEL_R753 }, - { PCI_VDEVICE(PLX, PCI_DEVICE_ID_PLX_OLITEC), INF_GAZEL_R753 }, - { } -}; -MODULE_DEVICE_TABLE(pci, infineon_ids); - -/* PCI interface specific defines */ -/* Diva 2.0/2.0U */ -#define DIVA_HSCX_PORT 0x00 -#define DIVA_HSCX_ALE 0x04 -#define DIVA_ISAC_PORT 0x08 -#define DIVA_ISAC_ALE 0x0C -#define DIVA_PCI_CTRL 0x10 - -/* DIVA_PCI_CTRL bits */ -#define DIVA_IRQ_BIT 0x01 -#define DIVA_RESET_BIT 0x08 -#define DIVA_EEPROM_CLK 0x40 -#define DIVA_LED_A 0x10 -#define DIVA_LED_B 0x20 -#define DIVA_IRQ_CLR 0x80 - -/* Diva 2.01/2.02 */ -/* Siemens PITA */ -#define PITA_ICR_REG 0x00 -#define PITA_INT0_STATUS 0x02 - -#define PITA_MISC_REG 0x1c -#define PITA_PARA_SOFTRESET 0x01000000 -#define PITA_SER_SOFTRESET 0x02000000 -#define PITA_PARA_MPX_MODE 0x04000000 -#define PITA_INT0_ENABLE 0x00020000 - -/* TIGER 100 Registers */ -#define TIGER_RESET_ADDR 0x00 -#define TIGER_EXTERN_RESET 0x01 -#define TIGER_AUX_CTRL 0x02 -#define TIGER_AUX_DATA 0x03 -#define TIGER_AUX_IRQMASK 0x05 -#define TIGER_AUX_STATUS 0x07 - -/* Tiger AUX BITs */ -#define TIGER_IOMASK 0xdd /* 1 and 5 are inputs */ -#define TIGER_IRQ_BIT 0x02 - -#define TIGER_IPAC_ALE 0xC0 -#define TIGER_IPAC_PORT 0xC8 - -/* ELSA (now Develo) PCI cards */ -#define ELSA_IRQ_ADDR 0x4c -#define ELSA_IRQ_MASK 0x04 -#define QS1000_IRQ_OFF 0x01 -#define QS3000_IRQ_OFF 0x03 -#define QS1000_IRQ_ON 0x41 -#define QS3000_IRQ_ON 0x43 - -/* Dr Neuhaus/Sagem Niccy */ -#define NICCY_ISAC_PORT 0x00 -#define NICCY_HSCX_PORT 0x01 -#define NICCY_ISAC_ALE 0x02 -#define NICCY_HSCX_ALE 0x03 - -#define NICCY_IRQ_CTRL_REG 0x38 -#define NICCY_IRQ_ENABLE 0x001f00 -#define NICCY_IRQ_DISABLE 0xff0000 -#define NICCY_IRQ_BIT 0x800000 - - -/* Scitel PLX */ -#define SCT_PLX_IRQ_ADDR 0x4c -#define SCT_PLX_RESET_ADDR 0x50 -#define SCT_PLX_IRQ_ENABLE 0x41 -#define SCT_PLX_RESET_BIT 0x04 - -/* Gazel */ -#define GAZEL_IPAC_DATA_PORT 0x04 -/* Gazel PLX */ -#define GAZEL_CNTRL 0x50 -#define GAZEL_RESET 0x04 -#define GAZEL_RESET_9050 0x40000000 -#define GAZEL_INCSR 0x4C -#define GAZEL_ISAC_EN 0x08 -#define GAZEL_INT_ISAC 0x20 -#define GAZEL_HSCX_EN 0x01 -#define GAZEL_INT_HSCX 0x04 -#define GAZEL_PCI_EN 0x40 -#define GAZEL_IPAC_EN 0x03 - - -static LIST_HEAD(Cards); -static DEFINE_RWLOCK(card_lock); /* protect Cards */ - -static void -_set_debug(struct inf_hw *card) -{ - card->ipac.isac.dch.debug = debug; - card->ipac.hscx[0].bch.debug = debug; - card->ipac.hscx[1].bch.debug = debug; -} - -static int -set_debug(const char *val, struct kernel_param *kp) -{ - int ret; - struct inf_hw *card; - - ret = param_set_uint(val, kp); - if (!ret) { - read_lock(&card_lock); - list_for_each_entry(card, &Cards, list) - _set_debug(card); - read_unlock(&card_lock); - } - return ret; -} - -MODULE_AUTHOR("Karsten Keil"); -MODULE_LICENSE("GPL v2"); -MODULE_VERSION(INFINEON_REV); -module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "infineon debug mask"); -module_param(irqloops, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(irqloops, "infineon maximal irqloops (default 4)"); - -/* Interface functions */ - -IOFUNC_IO(ISAC, inf_hw, isac.a.io) -IOFUNC_IO(IPAC, inf_hw, hscx.a.io) -IOFUNC_IND(ISAC, inf_hw, isac.a.io) -IOFUNC_IND(IPAC, inf_hw, hscx.a.io) -IOFUNC_MEMIO(ISAC, inf_hw, u32, isac.a.p) -IOFUNC_MEMIO(IPAC, inf_hw, u32, hscx.a.p) - -static irqreturn_t -diva_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = inb((u32)hw->cfg.start + DIVA_PCI_CTRL); - if (!(val & DIVA_IRQ_BIT)) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -diva20x_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = readb(hw->cfg.p); - if (!(val & PITA_INT0_STATUS)) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - writeb(PITA_INT0_STATUS, hw->cfg.p); /* ACK PITA INT0 */ - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -tiger_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = inb((u32)hw->cfg.start + TIGER_AUX_STATUS); - if (val & TIGER_IRQ_BIT) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -elsa_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = inb((u32)hw->cfg.start + ELSA_IRQ_ADDR); - if (!(val & ELSA_IRQ_MASK)) { - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -niccy_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u32 val; - - spin_lock(&hw->lock); - val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - if (!(val & NICCY_IRQ_BIT)) { /* for us or shared ? */ - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static irqreturn_t -gazel_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - irqreturn_t ret; - - spin_lock(&hw->lock); - ret = mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return ret; -} - -static irqreturn_t -ipac_irq(int intno, void *dev_id) -{ - struct inf_hw *hw = dev_id; - u8 val; - - spin_lock(&hw->lock); - val = hw->ipac.read_reg(hw, IPAC_ISTA); - if (!(val & 0x3f)) { - spin_unlock(&hw->lock); - return IRQ_NONE; /* shared */ - } - hw->irqcnt++; - mISDNipac_irq(&hw->ipac, irqloops); - spin_unlock(&hw->lock); - return IRQ_HANDLED; -} - -static void -enable_hwirq(struct inf_hw *hw) -{ - u16 w; - u32 val; - - switch (hw->ci->typ) { - case INF_DIVA201: - case INF_DIVA202: - writel(PITA_INT0_ENABLE, hw->cfg.p); - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - outb(TIGER_IRQ_BIT, (u32)hw->cfg.start + TIGER_AUX_IRQMASK); - break; - case INF_QS1000: - outb(QS1000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_QS3000: - outb(QS3000_IRQ_ON, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_NICCY: - val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - val |= NICCY_IRQ_ENABLE; - outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - break; - case INF_SCT_1: - w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - w |= SCT_PLX_IRQ_ENABLE; - outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - break; - case INF_GAZEL_R685: - outb(GAZEL_ISAC_EN + GAZEL_HSCX_EN + GAZEL_PCI_EN, - (u32)hw->cfg.start + GAZEL_INCSR); - break; - case INF_GAZEL_R753: - outb(GAZEL_IPAC_EN + GAZEL_PCI_EN, - (u32)hw->cfg.start + GAZEL_INCSR); - break; - default: - break; - } -} - -static void -disable_hwirq(struct inf_hw *hw) -{ - u16 w; - u32 val; - - switch (hw->ci->typ) { - case INF_DIVA201: - case INF_DIVA202: - writel(0, hw->cfg.p); - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - outb(0, (u32)hw->cfg.start + TIGER_AUX_IRQMASK); - break; - case INF_QS1000: - outb(QS1000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_QS3000: - outb(QS3000_IRQ_OFF, (u32)hw->cfg.start + ELSA_IRQ_ADDR); - break; - case INF_NICCY: - val = inl((u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - val &= NICCY_IRQ_DISABLE; - outl(val, (u32)hw->cfg.start + NICCY_IRQ_CTRL_REG); - break; - case INF_SCT_1: - w = inw((u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - w &= (~SCT_PLX_IRQ_ENABLE); - outw(w, (u32)hw->cfg.start + SCT_PLX_IRQ_ADDR); - break; - case INF_GAZEL_R685: - case INF_GAZEL_R753: - outb(0, (u32)hw->cfg.start + GAZEL_INCSR); - break; - default: - break; - } -} - -static void -ipac_chip_reset(struct inf_hw *hw) -{ - hw->ipac.write_reg(hw, IPAC_POTA2, 0x20); - mdelay(5); - hw->ipac.write_reg(hw, IPAC_POTA2, 0x00); - mdelay(5); - hw->ipac.write_reg(hw, IPAC_CONF, hw->ipac.conf); - hw->ipac.write_reg(hw, IPAC_MASK, 0xc0); -} - -static void -reset_inf(struct inf_hw *hw) -{ - u16 w; - u32 val; - - if (debug & DEBUG_HW) - pr_notice("%s: resetting card\n", hw->name); - switch (hw->ci->typ) { - case INF_DIVA20: - case INF_DIVA20U: - outb(0, (u32)hw->cfg.start + DIVA_PCI_CTRL); - mdelay(10); - outb(DIVA_RESET_BIT, (u32)hw->cfg.start + DIVA_PCI_CTRL); - mdelay(10); - /* Workaround PCI9060 */ - outb(9, (u32)hw->cfg.start + 0x69); - outb(DIVA_RESET_BIT | DIVA_LED_A, - (u32)hw->cfg.start + DIVA_PCI_CTRL); - break; - case INF_DIVA201: - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, - hw->cfg.p + PITA_MISC_REG); - mdelay(1); - writel(PITA_PARA_MPX_MODE, hw->cfg.p + PITA_MISC_REG); - mdelay(10); - break; - case INF_DIVA202: - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, - hw->cfg.p + PITA_MISC_REG); - mdelay(1); - writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET, - hw->cfg.p + PITA_MISC_REG); - mdelay(10); - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - ipac_chip_reset(hw); - hw->ipac.write_reg(hw, IPAC_ACFG, 0xff); - hw->ipac.write_reg(hw, IPAC_AOE, 0x00); - hw->ipac.write_reg(hw, IPAC_PCFG, 0x12); - break; - case INF_QS1000: - case INF_QS3000: - ipac_chip_reset(hw); - hw->ipac.write_reg(hw, IPAC_ACFG, 0x00); - hw->ipac.write_reg(hw, IPAC_AOE, 0x3c); - hw->ipac.write_reg(hw, IPAC_ATX, 0xff); - break; - case INF_NICCY: - break; - case INF_SCT_1: - w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - w &= (~SCT_PLX_RESET_BIT); - outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - mdelay(10); - w = inw((u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - w |= SCT_PLX_RESET_BIT; - outw(w, (u32)hw->cfg.start + SCT_PLX_RESET_ADDR); - mdelay(10); - break; - case INF_GAZEL_R685: - val = inl((u32)hw->cfg.start + GAZEL_CNTRL); - val |= (GAZEL_RESET_9050 + GAZEL_RESET); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - val &= ~(GAZEL_RESET_9050 + GAZEL_RESET); - mdelay(4); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - mdelay(10); - hw->ipac.isac.adf2 = 0x87; - hw->ipac.hscx[0].slot = 0x1f; - hw->ipac.hscx[1].slot = 0x23; - break; - case INF_GAZEL_R753: - val = inl((u32)hw->cfg.start + GAZEL_CNTRL); - val |= (GAZEL_RESET_9050 + GAZEL_RESET); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - val &= ~(GAZEL_RESET_9050 + GAZEL_RESET); - mdelay(4); - outl(val, (u32)hw->cfg.start + GAZEL_CNTRL); - mdelay(10); - ipac_chip_reset(hw); - hw->ipac.write_reg(hw, IPAC_ACFG, 0xff); - hw->ipac.write_reg(hw, IPAC_AOE, 0x00); - hw->ipac.conf = 0x01; /* IOM off */ - break; - default: - return; - } - enable_hwirq(hw); -} - -static int -inf_ctrl(struct inf_hw *hw, u32 cmd, u_long arg) -{ - int ret = 0; - - switch (cmd) { - case HW_RESET_REQ: - reset_inf(hw); - break; - default: - pr_info("%s: %s unknown command %x %lx\n", - hw->name, __func__, cmd, arg); - ret = -EINVAL; - break; - } - return ret; -} - -static int __devinit -init_irq(struct inf_hw *hw) -{ - int ret, cnt = 3; - u_long flags; - - if (!hw->ci->irqfunc) - return -EINVAL; - ret = request_irq(hw->irq, hw->ci->irqfunc, IRQF_SHARED, hw->name, hw); - if (ret) { - pr_info("%s: couldn't get interrupt %d\n", hw->name, hw->irq); - return ret; - } - while (cnt--) { - spin_lock_irqsave(&hw->lock, flags); - reset_inf(hw); - ret = hw->ipac.init(&hw->ipac); - if (ret) { - spin_unlock_irqrestore(&hw->lock, flags); - pr_info("%s: ISAC init failed with %d\n", - hw->name, ret); - break; - } - spin_unlock_irqrestore(&hw->lock, flags); - msleep_interruptible(10); - if (debug & DEBUG_HW) - pr_notice("%s: IRQ %d count %d\n", hw->name, - hw->irq, hw->irqcnt); - if (!hw->irqcnt) { - pr_info("%s: IRQ(%d) got no requests during init %d\n", - hw->name, hw->irq, 3 - cnt); - } else - return 0; - } - free_irq(hw->irq, hw); - return -EIO; -} - -static void -release_io(struct inf_hw *hw) -{ - if (hw->cfg.mode) { - if (hw->cfg.p) { - release_mem_region(hw->cfg.start, hw->cfg.size); - iounmap(hw->cfg.p); - } else - release_region(hw->cfg.start, hw->cfg.size); - hw->cfg.mode = AM_NONE; - } - if (hw->addr.mode) { - if (hw->addr.p) { - release_mem_region(hw->addr.start, hw->addr.size); - iounmap(hw->addr.p); - } else - release_region(hw->addr.start, hw->addr.size); - hw->addr.mode = AM_NONE; - } -} - -static int __devinit -setup_io(struct inf_hw *hw) -{ - int err = 0; - - if (hw->ci->cfg_mode) { - hw->cfg.start = pci_resource_start(hw->pdev, hw->ci->cfg_bar); - hw->cfg.size = pci_resource_len(hw->pdev, hw->ci->cfg_bar); - if (hw->ci->cfg_mode == AM_MEMIO) { - if (!request_mem_region(hw->cfg.start, hw->cfg.size, - hw->name)) - err = -EBUSY; - } else { - if (!request_region(hw->cfg.start, hw->cfg.size, - hw->name)) - err = -EBUSY; - } - if (err) { - pr_info("mISDN: %s config port %lx (%lu bytes)" - "already in use\n", hw->name, - (ulong)hw->cfg.start, (ulong)hw->cfg.size); - return err; - } - if (hw->ci->cfg_mode == AM_MEMIO) - hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size); - hw->cfg.mode = hw->ci->cfg_mode; - if (debug & DEBUG_HW) - pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n", - hw->name, (ulong)hw->cfg.start, - (ulong)hw->cfg.size, hw->ci->cfg_mode); - - } - if (hw->ci->addr_mode) { - hw->addr.start = pci_resource_start(hw->pdev, hw->ci->addr_bar); - hw->addr.size = pci_resource_len(hw->pdev, hw->ci->addr_bar); - if (hw->ci->addr_mode == AM_MEMIO) { - if (!request_mem_region(hw->addr.start, hw->addr.size, - hw->name)) - err = -EBUSY; - } else { - if (!request_region(hw->addr.start, hw->addr.size, - hw->name)) - err = -EBUSY; - } - if (err) { - pr_info("mISDN: %s address port %lx (%lu bytes)" - "already in use\n", hw->name, - (ulong)hw->addr.start, (ulong)hw->addr.size); - return err; - } - if (hw->ci->addr_mode == AM_MEMIO) - hw->addr.p = ioremap(hw->addr.start, hw->addr.size); - hw->addr.mode = hw->ci->addr_mode; - if (debug & DEBUG_HW) - pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n", - hw->name, (ulong)hw->addr.start, - (ulong)hw->addr.size, hw->ci->addr_mode); - - } - - switch (hw->ci->typ) { - case INF_DIVA20: - case INF_DIVA20U: - hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX; - hw->isac.mode = hw->cfg.mode; - hw->isac.a.io.ale = (u32)hw->cfg.start + DIVA_ISAC_ALE; - hw->isac.a.io.port = (u32)hw->cfg.start + DIVA_ISAC_PORT; - hw->hscx.mode = hw->cfg.mode; - hw->hscx.a.io.ale = (u32)hw->cfg.start + DIVA_HSCX_ALE; - hw->hscx.a.io.port = (u32)hw->cfg.start + DIVA_HSCX_PORT; - break; - case INF_DIVA201: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->addr.mode; - hw->isac.a.p = hw->addr.p; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.p = hw->addr.p; - break; - case INF_DIVA202: - hw->ipac.type = IPAC_TYPE_IPACX; - hw->isac.mode = hw->addr.mode; - hw->isac.a.p = hw->addr.p; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.p = hw->addr.p; - break; - case INF_SPEEDWIN: - case INF_SAPHIR3: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->cfg.mode; - hw->isac.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE; - hw->isac.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT; - hw->hscx.mode = hw->cfg.mode; - hw->hscx.a.io.ale = (u32)hw->cfg.start + TIGER_IPAC_ALE; - hw->hscx.a.io.port = (u32)hw->cfg.start + TIGER_IPAC_PORT; - outb(0xff, (ulong)hw->cfg.start); - mdelay(1); - outb(0x00, (ulong)hw->cfg.start); - mdelay(1); - outb(TIGER_IOMASK, (ulong)hw->cfg.start + TIGER_AUX_CTRL); - break; - case INF_QS1000: - case INF_QS3000: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start; - hw->isac.a.io.port = (u32)hw->addr.start + 1; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = (u32)hw->addr.start; - hw->hscx.a.io.port = (u32)hw->addr.start + 1; - hw->hscx.mode = hw->addr.mode; - break; - case INF_NICCY: - hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX; - hw->isac.mode = hw->addr.mode; - hw->isac.a.io.ale = (u32)hw->addr.start + NICCY_ISAC_ALE; - hw->isac.a.io.port = (u32)hw->addr.start + NICCY_ISAC_PORT; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.io.ale = (u32)hw->addr.start + NICCY_HSCX_ALE; - hw->hscx.a.io.port = (u32)hw->addr.start + NICCY_HSCX_PORT; - break; - case INF_SCT_1: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_SCT_2: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start + 0x08; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_SCT_3: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start + 0x10; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_SCT_4: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.a.io.ale = (u32)hw->addr.start + 0x20; - hw->isac.a.io.port = hw->isac.a.io.ale + 4; - hw->isac.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - hw->hscx.mode = hw->addr.mode; - break; - case INF_GAZEL_R685: - hw->ipac.type = IPAC_TYPE_ISAC | IPAC_TYPE_HSCX; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->addr.mode; - hw->isac.a.io.port = (u32)hw->addr.start; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.io.port = hw->isac.a.io.port; - break; - case INF_GAZEL_R753: - hw->ipac.type = IPAC_TYPE_IPAC; - hw->ipac.isac.off = 0x80; - hw->isac.mode = hw->addr.mode; - hw->isac.a.io.ale = (u32)hw->addr.start; - hw->isac.a.io.port = (u32)hw->addr.start + GAZEL_IPAC_DATA_PORT; - hw->hscx.mode = hw->addr.mode; - hw->hscx.a.io.ale = hw->isac.a.io.ale; - hw->hscx.a.io.port = hw->isac.a.io.port; - break; - default: - return -EINVAL; - } - switch (hw->isac.mode) { - case AM_MEMIO: - ASSIGN_FUNC_IPAC(MIO, hw->ipac); - break; - case AM_IND_IO: - ASSIGN_FUNC_IPAC(IND, hw->ipac); - break; - case AM_IO: - ASSIGN_FUNC_IPAC(IO, hw->ipac); - break; - default: - return -EINVAL; - } - return 0; -} - -static void -release_card(struct inf_hw *card) { - ulong flags; - int i; - - spin_lock_irqsave(&card->lock, flags); - disable_hwirq(card); - spin_unlock_irqrestore(&card->lock, flags); - card->ipac.isac.release(&card->ipac.isac); - free_irq(card->irq, card); - mISDN_unregister_device(&card->ipac.isac.dch.dev); - release_io(card); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - switch (card->ci->typ) { - case INF_SCT_2: - case INF_SCT_3: - case INF_SCT_4: - break; - case INF_SCT_1: - for (i = 0; i < 3; i++) { - if (card->sc[i]) - release_card(card->sc[i]); - card->sc[i] = NULL; - } - default: - pci_disable_device(card->pdev); - pci_set_drvdata(card->pdev, NULL); - break; - } - kfree(card); - inf_cnt--; -} - -static int __devinit -setup_instance(struct inf_hw *card) -{ - int err; - ulong flags; - - snprintf(card->name, MISDN_MAX_IDLEN - 1, "%s.%d", card->ci->name, - inf_cnt + 1); - write_lock_irqsave(&card_lock, flags); - list_add_tail(&card->list, &Cards); - write_unlock_irqrestore(&card_lock, flags); - - _set_debug(card); - card->ipac.isac.name = card->name; - card->ipac.name = card->name; - card->ipac.owner = THIS_MODULE; - spin_lock_init(&card->lock); - card->ipac.isac.hwlock = &card->lock; - card->ipac.hwlock = &card->lock; - card->ipac.ctrl = (void *)&inf_ctrl; - - err = setup_io(card); - if (err) - goto error_setup; - - card->ipac.isac.dch.dev.Bprotocols = - mISDNipac_init(&card->ipac, card); - - if (card->ipac.isac.dch.dev.Bprotocols == 0) - goto error_setup; - - err = mISDN_register_device(&card->ipac.isac.dch.dev, - &card->pdev->dev, card->name); - if (err) - goto error; - - err = init_irq(card); - if (!err) { - inf_cnt++; - pr_notice("Infineon %d cards installed\n", inf_cnt); - return 0; - } - mISDN_unregister_device(&card->ipac.isac.dch.dev); -error: - card->ipac.release(&card->ipac); -error_setup: - release_io(card); - write_lock_irqsave(&card_lock, flags); - list_del(&card->list); - write_unlock_irqrestore(&card_lock, flags); - return err; -} - -static const struct inf_cinfo inf_card_info[] = { - { - INF_DIVA20, - "Dialogic Diva 2.0", - "diva20", - AM_IND_IO, AM_NONE, 2, 0, - &diva_irq - }, - { - INF_DIVA20U, - "Dialogic Diva 2.0U", - "diva20U", - AM_IND_IO, AM_NONE, 2, 0, - &diva_irq - }, - { - INF_DIVA201, - "Dialogic Diva 2.01", - "diva201", - AM_MEMIO, AM_MEMIO, 0, 1, - &diva20x_irq - }, - { - INF_DIVA202, - "Dialogic Diva 2.02", - "diva202", - AM_MEMIO, AM_MEMIO, 0, 1, - &diva20x_irq - }, - { - INF_SPEEDWIN, - "Sedlbauer SpeedWin PCI", - "speedwin", - AM_IND_IO, AM_NONE, 0, 0, - &tiger_irq - }, - { - INF_SAPHIR3, - "HST Saphir 3", - "saphir", - AM_IND_IO, AM_NONE, 0, 0, - &tiger_irq - }, - { - INF_QS1000, - "Develo Microlink PCI", - "qs1000", - AM_IO, AM_IND_IO, 1, 3, - &elsa_irq - }, - { - INF_QS3000, - "Develo QuickStep 3000", - "qs3000", - AM_IO, AM_IND_IO, 1, 3, - &elsa_irq - }, - { - INF_NICCY, - "Sagem NICCY", - "niccy", - AM_IO, AM_IND_IO, 0, 1, - &niccy_irq - }, - { - INF_SCT_1, - "SciTel Quadro", - "p1_scitel", - AM_IO, AM_IND_IO, 1, 5, - &ipac_irq - }, - { - INF_SCT_2, - "SciTel Quadro", - "p2_scitel", - AM_NONE, AM_IND_IO, 0, 4, - &ipac_irq - }, - { - INF_SCT_3, - "SciTel Quadro", - "p3_scitel", - AM_NONE, AM_IND_IO, 0, 3, - &ipac_irq - }, - { - INF_SCT_4, - "SciTel Quadro", - "p4_scitel", - AM_NONE, AM_IND_IO, 0, 2, - &ipac_irq - }, - { - INF_GAZEL_R685, - "Gazel R685", - "gazel685", - AM_IO, AM_IO, 1, 2, - &gazel_irq - }, - { - INF_GAZEL_R753, - "Gazel R753", - "gazel753", - AM_IO, AM_IND_IO, 1, 2, - &ipac_irq - }, - { - INF_NONE, - } -}; - -static const struct inf_cinfo * __devinit -get_card_info(enum inf_types typ) -{ - const struct inf_cinfo *ci = inf_card_info; - - while (ci->typ != INF_NONE) { - if (ci->typ == typ) - return ci; - ci++; - } - return NULL; -} - -static int __devinit -inf_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = -ENOMEM; - struct inf_hw *card; - - card = kzalloc(sizeof(struct inf_hw), GFP_KERNEL); - if (!card) { - pr_info("No memory for Infineon ISDN card\n"); - return err; - } - card->pdev = pdev; - err = pci_enable_device(pdev); - if (err) { - kfree(card); - return err; - } - card->ci = get_card_info(ent->driver_data); - if (!card->ci) { - pr_info("mISDN: do not have informations about adapter at %s\n", - pci_name(pdev)); - kfree(card); - pci_disable_device(pdev); - return -EINVAL; - } else - pr_notice("mISDN: found adapter %s at %s\n", - card->ci->full, pci_name(pdev)); - - card->irq = pdev->irq; - pci_set_drvdata(pdev, card); - err = setup_instance(card); - if (err) { - pci_disable_device(pdev); - kfree(card); - pci_set_drvdata(pdev, NULL); - } else if (ent->driver_data == INF_SCT_1) { - int i; - struct inf_hw *sc; - - for (i = 1; i < 4; i++) { - sc = kzalloc(sizeof(struct inf_hw), GFP_KERNEL); - if (!sc) { - release_card(card); - pci_disable_device(pdev); - return -ENOMEM; - } - sc->irq = card->irq; - sc->pdev = card->pdev; - sc->ci = card->ci + i; - err = setup_instance(sc); - if (err) { - pci_disable_device(pdev); - kfree(sc); - release_card(card); - break; - } else - card->sc[i - 1] = sc; - } - } - return err; -} - -static void __devexit -inf_remove(struct pci_dev *pdev) -{ - struct inf_hw *card = pci_get_drvdata(pdev); - - if (card) - release_card(card); - else - pr_debug("%s: drvdata already removed\n", __func__); -} - -static struct pci_driver infineon_driver = { - .name = "ISDN Infineon pci", - .probe = inf_probe, - .remove = __devexit_p(inf_remove), - .id_table = infineon_ids, -}; - -static int __init -infineon_init(void) -{ - int err; - - pr_notice("Infineon ISDN Driver Rev. %s\n", INFINEON_REV); - err = pci_register_driver(&infineon_driver); - return err; -} - -static void __exit -infineon_cleanup(void) -{ - pci_unregister_driver(&infineon_driver); -} - -module_init(infineon_init); -module_exit(infineon_cleanup); |